网络编程之粘包解决方案
#解决方案1一收一发
#server.py import socket server=socket.socket() server.bind(('192.168.15.57',8001)) server.listen(3) while 1: print('等待连接。。。') conn,addr=server.accept() res1=conn.recv(1024).decode('utf-8') print('res1:',res1) res2=conn.recv(1024).decode('utf-8') print('res2:',res2) #client.py import socket client=socket.socket() client.connect(('192.168.15.57',8001)) client.send('你好呀!!!'.encode('utf-8')) client.send('我叫赛丽亚^-^'.encode('utf-8')) while 1: pass client.close()
#解决方案2,先发送长度,在发送数据
#server.py import socket,subprocess,json server=socket.socket() server.bind(('192.168.15.57',8001)) server.listen(3) while 1: print('等待连接。。。') conn,addr=server.accept() print('连接成功!!!') while 1: print('等待接受指令。。。') from_client_cmd=conn.recv(1024).decode('utf-8') print('收到的命令:',from_client_cmd) if from_client_cmd.upper()=='Q': break sub_obj=subprocess.Popen(from_client_cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) out=sub_obj.stdout.read() err=sub_obj.stderr.read() if out: conn.send(json.dumps(len(out)).encode('gbk')) from_client_res=conn.recv(1024).decode('utf-8') if from_client_res : conn.send(out) elif err: conn.send(json.dumps(len(err)).encode('gbk')) from_client_res=conn.recv(1024).decode('utf-8') if from_client_res: conn.send(err) print('断开连接。。。') conn.close() #client.py import socket,json client=socket.socket() client.connect(('192.168.15.57',8001)) while 1: cmd=input('请输入命令:').replace(' ','') client.send(cmd.encode('utf-8')) if cmd.upper() == 'Q': break from_server_msglen=json.loads(client.recv(1024).decode('gbk')) print('服务端要发送的数据长度:',from_server_msglen) client.send(json.dumps(1).encode('utf-8')) from_server_msg=client.recv(from_server_msglen) print('接收到的数据长度:',len(from_server_msg)) print('收到的数据:') print(from_server_msg.decode('gbk')) print('断开连接。。。') client.close()
#解决方案3,自定义4字节报头,发送数据
#server.py import socket import struct import json import os tcp_server = socket.socket() ip_port = ('127.0.0.1',8001) #127.0.0.1本机的回环地址,供内部程序之间测试用的 tcp_server.bind(ip_port) tcp_server.listen() #客户端上传的文件路径,都放在这个路径下 client_file_path = r'D:\jj' conn,addr = tcp_server.accept() #首先接收到文件信息长度转换出来的4个字节的数据 file_info_stru = conn.recv(4) #解包文件信息的长度 file_info_len = struct.unpack('i',file_info_stru)[0] #然后接收文件的描述信息 client_file_info = conn.recv(file_info_len).decode('utf-8') #将接收到的json字符串反序列化 abc_file_info = json.loads(client_file_info) print('abc_file_info>>>',abc_file_info) client_file_size = abc_file_info['file_size'] recv_all_size = 0 #拼接一下全路径 client_full_path = client_file_path + '\\' + abc_file_info['file_name'] # client_full_path = os.path.join(client_file_path,abc_file_info['file_name']) with open(client_full_path,'wb') as f: while recv_all_size < client_file_size: every_recv_data = conn.recv(1024) f.write(every_recv_data) recv_all_size += len(every_recv_data) conn.send('小伙玩的行,上传成功!'.encode('utf-8')) conn.close() tcp_server.close() #client.py import socket import struct import os import json tcp_client = socket.socket() server_ip_port = ('127.0.0.1',8001) tcp_client.connect(server_ip_port) read_size = 1024 file_info = { 'file_path':r'D:\python_workspace\day030\aaa.mp4', 'file_name':'aaa.mp4', 'file_size':None, } #获取文件大小 file_size = os.path.getsize(file_info['file_path']) #将文件大小添加到文件信息的字典中 file_info['file_size'] = file_size #因为我们要发送的数据是字节类型,那么必须将字典转换为bytes类型,但是字典不能直接转换为bytes,所以我们想到了json, #通过json模块将字典类型的文件信息数据转换为了json类型的字符串 file_info_json = json.dumps(file_info) #获取了字符串的长度 file_info_len = len(file_info_json) #将长度打包为4个字节的数据, file_info_stru = struct.pack('i',file_info_len) #将打包好的4个自己的数据和我的文件信息数据一起发送给了服务端 tcp_client.send(file_info_stru) tcp_client.send(file_info_json.encode('utf-8')) #统计文件数据 all_file_data = b'' #统计文件数据长度 all_size_len = 0 with open(file_info['file_path'],'rb') as f: while all_size_len < file_size: every_read_data = f.read(read_size) all_file_data += every_read_data all_size_len += len(every_read_data) #发送每次读取的数据 tcp_client.send(every_read_data) print(tcp_client.recv(1024).decode('utf-8')) tcp_client.close()