Python TCP粘包分包解决方案:自定义协议类设计与实现

小林子
小林子
发布时间:2026-10-13 | 5人浏览过
原创

本文详细介绍如何在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数据包协议类的示例内容到此结束,希望能为您的开发工作提供参考。欢迎大家支持本站,获取更多技术分享。

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表