python TCP Socket的粘包和分包的处理详解的粘包和分包的处理详解
主要介绍了python TCP Socket的粘包和分包的处理详解,分享了相关代码示例,小编觉得还是挺不错的,具有
一定借鉴价值,需要的朋友可以参考下
概述概述
在进行TCP Socket开发时,都需要处理数据包粘包和分包的情况。本文详细讲解解决该问题的步骤。使用的语言是Python。
实际上解决该问题很简单,在应用层下,定义一个协议:消息头部+消息长度+消息正文即可。
那什么是粘包和分包呢?
关于分包和粘包关于分包和粘包
粘包:发送方发送两个字符串”hello”+”world”,接收方却一次性接收到了”helloworld”。
分包:发送方发送字符串”helloworld”,接收方却接收到了两个字符串”hello”和”world”。
虽然socket环境有以上问题,但是TCP传输数据能保证几点:
顺序不变。例如发送方发送hello,接收方也一定顺序接收到hello,这个是TCP协议承诺的,因此这点成为我们解决分
包、黏包问题的关键。
分割的包中间不会插入其他数据。
因此如果要使用socket通信,就一定要自己定义一份协议。目前最常用的协议标准是:消息头部(包头)+消息长度+消息正文
TCP为什么会分包为什么会分包
TCP是以段(Segment)为单位发送数据的,建立TCP链接后,有一个最大消息长度(MSS)。如果应用层数据包超过
MSS,就会把应用层数据包拆分,分成两个段来发送。这个时候接收端的应用层就要拼接这两个TCP包,才能正确处理数
据。
相关的,路由器有一个MTU( 最大传输单元),一般是1500字节,除去IP头部20字节,留给TCP的就只有MTU-20字节。所
以一般TCP的MSS为MTU-20=1460字节。
当应用层数据超过1460字节时,TCP会分多个数据包来发送。
扩展阅读
TCP的RFC定义MSS的默认值是536,这是因为 RFC 791里说了任何一个IP设备都得最少接收576尺寸的大小(实
际上来说576是拨号的网络的MTU,而576减去IP头的20个字节就是536)。
TCP为什么会粘包
有时候,TCP为了提高网络的利用率,会使用一个叫做Nagle的算法。该算法是指,发送端即使有要发送的数据,如果很少的
话,会延迟发送。如果应用层给TCP传送数据很快的话,就会把两个应用层数据包“粘”在一起,TCP最后只发一个TCP数据包
给接收端。
开发环境开发环境
Python版本:3.5.1
操作系统:Windows 10 x64
消息头部(包含消息长度)消息头部(包含消息长度)
消息头部不一定只能是一个字节比如0xAA什么的,也可以包含协议版本号,指令等,当然也可以把消息长度合并到消息头部
里,唯一的要求是包头长度要固定的,包体则可变长。下面是我自定义的一个包头:
版本号(版本号(ver)) 消息长度(消息长度(bodySize)) 指令(指令(cmd))
版本号,消息长度,指令数据类型都是无符号32位整型变量,于是这个消息长度固定为4×3=12字节。在Python由于没有类型
定义,所以一般是使用struct模块生成包头。示例:
import struct
import json
ver = 1
body = json.dumps(dict(hello="world"))
评论0