Python 解决粘包
发送数据包前 对包的长度进行计算
1. 比较low的方法是 len( package) 然后直接发送给接收端。这样会出现一个问题,就是接收端不知道你的这个 len(package)是几个字节,就也有可能会出现粘包问题。
2. 利用struct对包的长度打包为固定4个字节或8个字节。
3. struct.pack format参数为"i" 时只能打包长度为10的数字,那么还可以先将 长度 转换为一个json字符串,再打包。
Server端
# -*- coding:utf-8 -*- from socketserver import ThreadingTCPServer, StreamRequestHandler import struct import subprocess class MyRequestHandler(StreamRequestHandler): def handle(self): while True: print("connect from:", self.client_address) cmd = bytes.decode(self.request.recv(1024))
if not cmd: break res = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) err = res.stderr.read() if err: back_msg = err else: back_msg = res.stdout.read() self.request.send(struct.pack("i", len(back_msg))) self.request.send(back_msg) if __name__ == '__main__': tcp_Server = ThreadingTCPServer(("127.0.0.1", 8081), MyRequestHandler) tcp_Server.allow_reuse_address = True tcp_Server.serve_forever()
Client端
# -*- coding:utf-8 -*- import socket import struct host = "127.0.0.1" port = 8081 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((host, port)) while True: cmd = input(">>>>").strip() if not cmd: continue s.send(cmd.encode("utf-8")) package_len = s.recv(4) package_size = struct.unpack("i",package_len)[0] recv_size = 0 recv_bytes = b"" while recv_size < package_size: res = s.recv(1024) recv_bytes += res recv_size += len(res) print(recv_bytes.decode("utf-8")) s.close()