粘包现象:
-
在socket网络程序中,TCP和UDP分别是面向连接和非面向连接的。因此TCP的socket编程,收发两端(客户端和服务器端)都要有成对的socket,因此,发送端为了将多个发往接收端的包,更有效的发到对方,使用了优化方法(Nagle算法),将多次间隔较小、数据量小的数据,合并成一个大的数据块,然后进行封包。这样,接收端,就难于分辨出来了,必须提供科学的拆包机制
-
对于UDP,不会使用块的合并优化算法,这样,实际上目前认为,是由于UDP支持的是一对多的模式,所以接收端的skbuff(套接字缓冲区)采用了链式结构来记录每一个到达的UDP包,在每个UDP包中就有了消息头(消息来源地址,端口等信息),这样,对于接收端来说,就容易进行区分处理了。所以UDP不会出现粘包问题。
粘包现象理解:
socket模块sned以及recv实现底层原理
- send
- 作用:将内存中的数据通过网卡发送出去
- 底层原理:将数据从程序内存中拷贝到操作系统,通过操作系统调用网卡接口发送到远程
- recv
- 作用:接收远程发送的数据,传入参数单位为字节
- 底层原理:网卡接收远程发过来的数据,然后将数据从操作系统内存拷贝到应用程序内存中
不管是recv还是send都不是直接发送或者接收对方的数据,而是操作自己的操作系统的内存,并且不是一个send对应一个recv,是根据recv接收数据的大小而决定
TCP协议传输优化算法:Nagle算法
- 将数据比较小的包,并且时间间隔很短的包合并成一个包,调一次网卡io将数据发送到远程,节省调用网卡io的时间,粘包现象是TCP底层传输优化算法造成的。
粘包现象结局思路
- 客户端循环接收数据,使用while循环判断数据是否接收完毕
- 服务端返回诗句是打包报头发送给客户端,客户端根据报头发送的数据长度截取发送数据的真实长度
服务端:
- 制作固定长度的报头
- 将报头打包发送给客户端(使用struct模块打包数据)
- 再发送真实数据,通过while循环判断是否接收完毕,接收完了则跳出循环
客户端
- 接收报头,指定接收报头的长度,使用struct打包将服务端发送的报头按照指定模式解析
- 解析报头获得真实数据的长度描述
可使用内置模块struct打包与解析数据长度,
- i模式:4个字节长度
- l模式:8个字节长度