python 网络编程 粘包问题
1.粘包现象
TCP粘包是指发送方发送的若干包数据到接收方接收时粘成一包,从接收缓冲区看,后一包数据的头紧接着前一包数据的尾。
粘包出现原因
使用了优化方法(Nagle算法),将多次间隔较小、数据量小的数据,合并成一个大的数据块,然后进行封包。
简单得说,在流传输中出现,UDP不会出现粘包,因为它有消息边界
1发送端需要等缓冲区满才发送出去,造成粘包
2接收方不及时接收缓冲区的包,造成多个包接收
解决方法
接收方创建一预处理线程,对接收到的数据包进行预处理,将粘连的包分开。
TCP无保护消息边界的解决
针对这个问题,一般有3种解决方案:
(1)发送固定长度的消息
(2)把消息的尺寸与消息一块发送
(3)使用特殊标记来区分消息间隔
2.struct模块
该模块可以把一个类型,如数字,转成固定长度的bytes
可以转的类型:
![](https://img2018.cnblogs.com/blog/1595219/201902/1595219-20190219205200585-1655733013.png)
用法:
import struct ret = struct.pack('i',23333) #i表示int类型,把23333转成固定长度的bytes类型 struct.pack('i',ret) #把bytes转回int
3.例子
#以远程执行命令为例讲解决方法 #先发送传输的大小 服务端: import socket import struct sk = socket.socket() s = ('127.0.0.1', 8081) sk.bind(s) sk.listen(2) conn, addr = sk.accept() while 1: cmd = input('[cmd] #') if cmd == 'q': break conn.send(cmd.encode('utf-8')) lens = conn.recv(4) #接收包长度 lens = struct.unpack('i',lens)[0] info = conn.recv(lens) print(info.decode('gbk')) 客户端: import socket import subprocess import struct sk = socket.socket() sk.connect(('127.0.0.1',8081)) while 1: cmd = sk.recv(1024).decode('gbk') res = subprocess.Popen(cmd,shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) std = res.stdout.read()+res.stderr.read() lens = len(std) lens = struct.pack('i', lens) #把长度转成4个字节的bytes sk.send(lens) sk.send(std)