Python socket粘包问题(初级解决办法)
server端配置:
import socket,subprocess,struct from socket import * server=socket(AF_INET,SOCK_STREAM) server.bind(('127.0.0.1',8080)) server.listen(5) while True: conn,client_addr=server.accept() while True: try: cmd=conn.recv(1024) if len(cmd) == 0:break obj=subprocess.Popen( cmd.decode('utf-8'), shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, ) out=obj.stdout.read() #bytes类型 err=obj.stderr.read() print(len(out+err)) # 解决粘包问题的步骤,先发型数据的长度 total_size=len(out)+len(err) #数据类型,1.变为bytes类型 2.还是个固定长度 #1.制作固定长度的包头 header=struct.pack('i',total_size) #2.发送报头 conn.send(header) #固定数据报的head头的大小(自定义数据) #下面是发送真是的数据 # conn.send(out+err) #2个包是一起发过去的,因为间隔短 conn.send(out) conn.send(err) #发过去的整体是一个数据报=报头+数据部分 except ConnectionResetError: break conn.close() server.close()
client端配置:
import socket import socket,struct client=socket.socket(socket.AF_INET,socket.SOCK_STREAM) client.connect(('127.0.0.1',8080)) while True: cmd=input('输入执行的命令:') if len(cmd) == 0: continue client.send(cmd.encode('utf-8')) #1.先收固定长度的的包头默认stuck就是固定了长度为4 header=client.recv(4) #第二次再收不是下一个包头,是上次命令的残留 #2.解析包头 total_size=struct.unpack('i',header)[0] #拿到的是个元祖,元祖的0就是这个长度值 print(total_size) #3.根据包头内的信息,收取真实数据 # client.recv(total_size) 因为现实数据量太大的时候就不行,所以考虑while循环 #思考如果数据大,total_size数据会特别大就会直接报错 #为了解决输入较大程序,定义一个小的变量,循环一点点就去收 recv_size=0 res=b'' while recv_size < total_size: recv_data=client.recv(1024) #recv_data是bytes类型,是唯一真实的值,有多少就会收多少 res+=recv_data recv_size+=len(recv_data) print(res.decode('gbk')) client.close()