天天看点

tcp 粘包一、TCP 长连接和短连接二、基于消息和基于流传输三、粘包原因四、粘包处理

文章目录

  • 一、TCP 长连接和短连接
  • 二、基于消息和基于流传输
  • 三、粘包原因
  • 四、粘包处理

一、TCP 长连接和短连接

  • 长连接: Client方与Server方先建立通讯连接,连接建立后不断开, 然后再进行报文发送和接收
  • 短连接: Client方与Server每进行一次报文收发交易时才进行通讯连接,交易完毕后立即断开连接。此种方式常用于一点对多点通讯,比如多个Client连接一个Server

二、基于消息和基于流传输

  • UDP基于消息传输,接收端的skbuff(套接字缓冲区)采用了链式结构来记录每一个到达的UDP包,每个UDP包中就有了消息头(消息来源地址,端口等信息),也就是说存在消息边界,接收端一次只能接收发送端发出的一个数据包,所以UDP不会出现粘包问题
  • TCP基于流传输,消息是没有边界的,发送端为了将多个包更有效的发到对方,使用了优化方法(Nagle算法),将多次间隔较小、数据量小的数据,合并成一个大的数据块发送给对端,这样接收端就难于分辨出来了,有可能在一次接收动作中会接收两个或者更多的数据包,很多人往往会忽视这一点,只解析检查了第一个数据包,而已经接收的其他数据包却被丢掉了

例如,我们连续发送大小分别是2k,4k ,8k 三个数据包,如果使用UDP协议,不管我们使用多大的接收缓冲区去接收数据,我们必须有三次接收动作才能够把所有的数据包接收完,而使用TCP协议,我们只要把接收的缓冲区大小设置在14k以上,我们只需要有一次接收动作就能够把所有的数据包接收下来

三、粘包原因

TCP粘包是指发送方发送的若干包数据到接收方接收时粘成一包,后一包数据的头紧接着前一包数据的尾,出现粘包的原因可能由发送方造成,也可能由接收方造成

  • 发送端:发送方引起的粘包是由TCP协议本身造成的,TCP为提高传输效率采用Nagle算法,收集到足够多的数据后才发送一包数据,这样接收方就收到了粘包数据
  • 接收端:接收方引起的粘包是由于接收方用户进程不及时接收数据,从而导致粘包现象。这是因为接收方先把收到的数据放在系统接收缓冲区,用户进程从该缓冲区取数据,若下一包数据到达时前一包数据尚未被用户进程取走,则下一包数据放到系统接收缓冲区时就接到前一包数据之后,这样就一次取到了多包数据

四、粘包处理

  • 数据为不带结构的连续流数据(如文件传输),则不必处理粘包不必把粘连的包分开
  • 数据为带结构的数据且数据结构定长时,分包算法比较简单,每次去固定长度数据解析即可
  • 数据为带结构的数据且数据结构不定长时,分包算法就比较复杂,特别是粘在一起的包有不完整的情况,实际工程应用中应尽量避免出现粘包现象
    • 对于发送方引起的粘包,用户可通过编程设置来避免,通过设置 SO_NODELAY 选项关闭Nagle算法,则发送方就立即将数据发送出去,而不必等待收集多个数据包。但这样降低了网络发送效率,影响应用程序的性能,一般不建议使用
    • 对于接收方引起的粘包,则可通过精简接收进程工作量、提高接收进程优先级等措施,使其及时接收数据,从而尽量避免出现粘包现象。这种方法只能减少出现粘包的可能性,但并不能完全避免粘包
    • 应用层发送端设置特殊的四字节起始和结束标识,并添加四字节消息长度字段,即设置固定长度的应用层包头结构。在接收端首先循环接收数据直到收到包头长度的数据,然后解析出消息长度字段,最后再循环接收数据直到收到该消息长度的数据

继续阅读