一 粘包现象
首先我们要知道什么是粘包:
我们首先要知道,粘包是对于TCP来说的,UDP是不存在粘包一说的,那么TCP在传输数据的过程的特点是什么呢:
1 会将数据量较小,且发送时间间隔较短的的数据一起打包发送,那么这里所讲的时间较短是相比较网络延迟来说的,
比如我们两次发送间隔为0.00001秒,那么网络延迟为0.001,这个时候两次的数据就会打包发送,这是一种优化机制。 2 TCP协议发送数据时,是源源不断的发送,像水流一样,因此TCP又叫流式协议。
我们知道服务端在接收消息时是有一个最大限制的=====>conn.recv(1024),1024表示1024个bytes。那么如果我们一次传输的数据超过了1024bytes,剩余的数据会存在我们接收端计算机操作系统缓存中,也就是说,接收方并不知道发送方传输了多少数据,所以这个时候问题就出现了,发送方引起的粘包是由TCP协议本身造成的,TCP为提高传输效率,发送方往往要收集到足够多的数据后才发送一个TCP段。若连续几次需要send的数据都很少,通常TCP会根据优化算法把这些数据合成一个TCP段后一次发送出去,这样接收方就收到了粘包数据。
- TCP(transport control protocol,传输控制协议)是面向连接的,面向流的,提供高可靠性服务。收发两端(客户端和服务器端)都要有一一成对的socket,因此,发送端为了将多个发往接收端的包,更有效的发到对方,使用了优化方法(Nagle算法),将多次间隔较小且数据量小的数据,合并成一个大的数据块,然后进行封包。这样,接收端,就难于分辨出来了,必须提供科学的拆包机制。 即面向流的通信是无消息保护边界的。
- UDP(user datagram protocol,用户数据报协议)是无连接的,面向消息的,提供高效率服务。不会使用块的合并优化算法,, 由于UDP支持的是一对多的模式,所以接收端的skbuff(套接字缓冲区)采用了链式结构来记录每一个到达的UDP包,在每个UDP包中就有了消息头(消息来源地址,端口等信息),这样,对于接收端来说,就容易进行区分处理了。 即面向消息的通信是有消息保护边界的。
- tcp是基于数据流的,于是收发的消息不能为空,这就需要在客户端和服务端都添加空消息的处理机制,防止程序卡住,而udp是基于数据报的,即便是你输入的是空内容(直接回车),那也不是空消息,udp协议会帮你封装上消息头。
须知:只有TCP有粘包现象,UDP永远不会粘包,为何,且听我娓娓道来
首先需要掌握一个socket收发消息的原理
二 粘包发生的场景:
第一种:发送端需要等缓冲区满才发送出去,造成粘包(发送数据时间间隔很短,数据了很小,会合到一起,产生粘包)
from socket import * ip_port=('127.0.0.1',8080) tcp_socket_server=socket(AF_INET,SOCK_STREAM) tcp_socket_server.bind(ip_port) tcp_socket_server.listen(5) conn,addr=tcp_socket_server.accept() data1=conn.recv(10) data2=conn.recv(10) print('----->',data1.decode('utf-8')) print('----->',data2.decode('utf-8')) conn.close()