TCP沾包处理
TCP沾包是指在TCP协议传输数据时,发送的数据之间没有边界,在接收时所有的数据混合在一起,无法区分每次发送的数据内容。
在数据发送和接收的时候,都要先把数据放到缓存区,然后再执行发送或接收操作。当消息很长,超出缓冲区大小时(一般不会出现),一条消息会分几次发送,在接受方收到消息后解码时可能会出错。如果接收方的缓冲区空间较小,一次无法接收发送方发送的消息,也会分几次接收数据。
下面举例说明沾包的现象。
TCP服务器端程序
from socket import *
#创建流式套接字
sockfd = socket()
#绑定IP端口
sockfd.bind(('127.0.0.1',8888))
#设置监听套接字,创建监听队列
sockfd.listen(5)
while True:
#等待客户端链接
connfd,addr = sockfd.accept()
print("connect from",addr)
while True:
#收发消息
data = connfd.recv(1024)
if not data:
break
print(data.decode())
#发消息
connfd.send('收到你的消息了!'.encode())
#关闭套接字
connfd.close()
sockfd.close()
TCP客户端程序
from socket import *
import time
#创建套接字
sockfd = socket(AF_INET,SOCK_STREAM)
#发起连接
sockfd.connect(('127.0.0.1',8888))
l=['诸葛亮','刘备','关羽','张飞','赵云']
for i in l:
sockfd.send(i.encode())
#time.sleep(0.1)
#接收消息
data = sockfd.recv(1024)
print(data.decode())
#关闭
sockfd.close()
说明:
程序在客户端发送消息,每次发送的消息是列表中的一项,服务端接收到消息后会打印接受的消息。观察沾包的现象,首先把TCP客户端程序的第十行(time.sleep(0.1))注释掉,运行程序,观察服务器端接收的消息,会有如下现象:
客户端分5次发送的消息,在服务器端一次接收完毕,我们想要的结果是将客户端每次发送的消息分别打印在一行,总共打印5行,但是实际情况是5条消息显示在1行中,这就是沾包的现象。
为了预防沾包,对程序做一下修改,将TCP客户端的第十行不要注释,也就是在每发送一次消息后,程序暂停0.1秒,再继续执行。同样运行程序,观察到服务器端的现象如下:
这次的输出结果与我们想要的结果一致。所以,在使用TCP协议传输消息时,要注意沾包的问题。
为了预防TCP传输时的沾包,可以采取如下措施:1、每次发送消息后sleep一段时间(0.1秒即可);2、发送消息时可以采取消息结尾加特殊字符作为标记,接收端收到消息后判断消息是否完整,不完整继续接收。