Python TCP粘包分包解决方案:自定义协议类设计与实现
本文详细介绍如何在Python中通过自定义协议类解决TCP通信中的粘包与分包问题。文章设计了包含4字节长度头和数据域的结构,定义了定长整型与变长字符串的编码规则,并提供了完整的Python代码实现,涵盖数据包的组装与解析逻辑,帮助开发者构建稳定的网络通信基础。
TCP粘包问题背景
一、问题背景
在TCP网络编程中,最核心的挑战在于处理粘包和分包现象。为了解决这一问题,通常需要在每个数据包头部添加长度信息,以便接收端能够准确识别并分割粘连的数据流。
自定义协议结构设计
二、协议结构设计
数据包的基本组成包括两部分:长度字段和数据域。
长度字段占用4个字节,用于存储后续数据域的字节长度。
数据域由多个变量构成。对于定长变量,无需额外存储长度信息;对于变长变量,则需要包含长度标识。
在本设计中,我们规定整数(int)为4字节的定长变量。
字符串被视为变长变量,需要处理其长度信息。
为了更直观地理解,请参考以下结构图示:

图示第一行展示了整个数据包的总体结构。
第二行展示了数据域内部的结构,其中变量的数量和位置由开发者自定义,上图仅为示例。
第三行展示了具体变量的存储结构。
如果对上述结构仍有疑问,我们可以通过一个具体实例来进一步说明。
假设我们需要构建一个包含特定数据域的数据包。
该数据域包含四个变量:整数666、字符串“你好啊”、字符串“hello”以及整数888。
经过封装后,生成的数据包结构如下所示:

理解上述结构后,接下来我们将使用Python代码封装一个类,以实现该结构数据包的组装与解析功能。
Python代码实现方案
三、代码实现
class Protocol:
"""
规定:
数据包头部占4字节
整型占4字节
字符串长度位占2字节
字符串不定长
"""
def __init__(self, bs=None):
"""
如果bs为None则代表需要创建一个数据包
否则代表需要解析一个数据包
"""
if bs:
self.bs = bytearray(bs)
else:
self.bs = bytearray(0)
def get_int32(self):
try:
ret = self.bs[:4]
self.bs = self.bs[4:]
return int.from_bytes(ret, byteorder='little')
except:
raise Exception("数据异常!")
def get_str(self):
try:
# 拿到字符串字节长度(字符串长度位2字节)
length = int.from_bytes(self.bs[:2], byteorder='little')
# 再拿字符串
ret = self.bs[2:length + 2]
# 删掉取出来的部分
self.bs = self.bs[2 + length:]
return ret.decode(encoding='utf8')
except:
raise Exception("数据异常!")
def add_int32(self, val):
bytes_val = bytearray(val.to_bytes(4, byteorder='little'))
self.bs += bytes_val
def add_str(self, val):
bytes_val = bytearray(val.encode(encoding='utf8'))
bytes_length = bytearray(len(bytes_val).to_bytes(2, byteorder='little'))
self.bs += (bytes_length + bytes_val)
def get_pck_not_head(self):
return self.bs
def get_pck_has_head(self):
bytes_pck_length = bytearray(len(self.bs).to_bytes(4, byteorder='little'))
return bytes_pck_length + self.bs
if __name__ == '__main__':
p = Protocol()
p.add_int32(666)
p.add_str("你好啊")
p.add_str("hello")
p.add_int32(888)
r = Protocol(p.get_pck_not_head())
print(r.get_int32())
print(r.get_str())
print(r.get_str())
print(r.get_int32())
提供的代码示例较为简洁,且未涵盖所有边界情况,请根据实际业务需求进行适当修改和完善。
以上关于Python设计TCP数据包协议类的示例内容到此结束,希望能为您的开发工作提供参考。欢迎大家支持本站,获取更多技术分享。
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









