湖南大学计算机网络实验二------水
计算机网络实验二 网络基础编程实验(Python3)
由于这一次实验2.1-2.3都是给了代码的,所以没有写了,只写了2.3的对比和2.4的代码,实现互通信
2.3 多线程/线程池对比(python3.5)
- 多线程:每处理一个socket请求都会新建一个线程 类似于临时工简单的为每一个socket都开一个线程,将socket作为参数传进去即可。优点:合理利用CPU资源。并且可以提高程序的运行效率缺点:如果有大量的线程运行,会消耗大部分内存,会影响性能(可能会死机),CPU需要他们之间的切换线程运行可能会出现死锁、线程安全问题
- 线程池:提前创建好多个线程,然后需要就从线程池里拿,用完换回去即可 类似于长期工优点:如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了,这样频繁创建线程,并且大量线程空闲,就会大大降低系统的效率,因为频繁创建线程和销毁线程需要时间。这个时候,线程池的作用就出来了,当程序需要创建大量生命周期很短暂的线程时,使用线程池可以有效控制系统中并发线程的数量,线程池中,一个线程于空闲状态时,可以被使用,使用时变为阻塞状态,使用后又变成空闲状态,这样就可以实现线程的重复利用
多线程与单线程的传输连接的不同点也在于连接的声明方式,即为每一个连接客户端建立一个线程,连接将使用Threading方法,被如下声明:

2.4 写一个简单的chat程序,并能互传文件,编程语言不限。
先放效果图(真的很傻,但是够应付实验了)

#!/usr/bin/env python
#coding:utf-8import socket
import sys
import osip_port = ('127.0.0.1',9999)
sk = socket.socket()
sk.connect(ip_port)
base_path = 'E:\\Junior_1\计算机网络\lab2'
container = {'key':'','data':''}
while True:FLAG = input('0.收文件存到basepath下 1.传path目录下文件存到srv的basepath1下\n')sk.sendall(str(FLAG).encode('utf-8'))if FLAG=='1':# 客户端输入要上传文件的路径path = 'E:\\qq_file_receive\pic.gif'# 根据路径获取文件名file_name = os.path.basename(path)# print(file_name)# 获取文件大小file_size = os.stat(path).st_size# 发送文件名 和 文件大小Informf = (file_name + '|' + str(file_size))sk.send(Informf.encode())# 为了防止粘包,将文件名和大小发送过去之后,等待服务端收到,直到从服务端接受一个信号(说明服务端已经收到)message=sk.recv(1024)print(message.decode())send_size = 0f = open(path, 'rb')Flag = Truewhile Flag:if send_size + 1024 > file_size:data = f.read(file_size - send_size)Flag = Falseelse:data = f.read(1024)send_size += 1024sk.send(data)msg = sk.recv(1024)print(msg.decode())f.close()else :message=sk.recv(1024)print(message.decode(encoding='utf8'))message = input('请求文件名: ')message = str(message)# 发送数据 加码sk.sendall(message.encode('utf-8'))print('A等待.....')pre_data = sk.recv(1024).decode()# 获取请求方法、文件名、文件大小file_name, file_size = pre_data.split('|')# 防止粘包,给客户端发送一个信号。sk.sendall('get'.encode())# 已经接收文件的大小recv_size = 0# 上传文件路径拼接file_dir = os.path.join(base_path, message)f = open(file_dir, 'wb')Flag = Truewhile Flag:# 未上传完毕,if int(file_size) > recv_size:# 最多接收1024,可能接收的小于1024data = sk.recv(1024)recv_size += len(data)# 写入文件f.write(data)# 上传完毕,则退出循环else:recv_size = 0Flag = Falsesk.sendall('下载完成'.encode())print('upload successed.')f.close()
sk.close()
#!/usr/bin/env python
#coding:utf-8import socketserver
import osclass MyServer(socketserver.BaseRequestHandler):def handle(self):base_path = 'E:\\Junior_1\计算机网络'conn = self.requestprint ('connected...')while True:order = conn.recv(1024).decode(encoding='utf8')print(order)if order == '1':pre_data = conn.recv(1024).decode()# 获取请求方法、文件名、文件大小file_name, file_size = pre_data.split('|')# 防止粘包,给客户端发送一个信号。conn.sendall('收到'.encode())# 已经接收文件的大小recv_size = 0# 上传文件路径拼接file_dir = os.path.join(base_path, file_name)f = open(file_dir, 'wb')Flag = Truewhile Flag:# 未上传完毕,if int(file_size) > recv_size:# 最多接收1024,可能接收的小于1024data = conn.recv(1024)recv_size += len(data)# 写入文件f.write(data)# 上传完毕,则退出循环else:recv_size = 0Flag = Falseconn.sendall('下载完成'.encode())print('upload successed.')f.close()if order == '0':conn.sendall('B准备发送文件啦'.encode('utf-8'))path = conn.recv(1024).decode()file_name = os.path.join(base_path, path)print(file_name)# file_name = os.path.basename(path)# print(file_name)# 获取文件大小file_size = os.stat(file_name).st_size# 发送文件名 和 文件大小Informf = (file_name + '|' + str(file_size))conn.send(Informf.encode())# 为了防止粘包,将文件名和大小发送过去之后,等待服务端收到,直到从服务端接受一个信号(说明服务端已经收到)me=conn.recv(1024).decode()print(me)send_size = 0f = open(file_name, 'rb')Flag = Truewhile Flag:if send_size + 1024 > file_size:data = f.read(file_size - send_size)Flag = Falseelse:data = f.read(1024)send_size += 1024conn.send(data)conn.recv(1024)f.close()instance = socketserver.ThreadingTCPServer(('127.0.0.1',9999),MyServer)
instance.serve_forever()#(服务端)
可能有线程安全问题,搞多线程又不标识线程号不保护,但是实验二应该也不会要求这么多把。
反正一个线程跑是莫得问题的
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
