【导读】在socket通信中,通信内核层会做缓冲,使得前后两次发送的数据缓冲到一起,导致接收方接收到的数据是一整块,无法区分。
【正文】
1. 在发送方和接收方约定相同的长度,发送方进行用特殊的标志对数据进行末尾补齐,接收方将数据过滤掉特殊的标志。
示例:双方约定能处理的最大数据长度是1024,
发送方:发送字符串"abc"时,有效长度是3,需要补齐 1024 - 3 = 1021个“\0”字符(不同编程语言里,这个特殊的字符需要看情况指定)。python代码:
class Session():
BUFF_SIZE = 512
TAG_STR = "\0"
def __preprocess_send_data(self, data):
str_len = len(data)
need_num = Session.BUFF_SIZE - str_len % Session.BUFF_SIZE
final_len = str_len + need_num
tmp_data = data + need_num * Session.TAG_STR
data_list = []
for i in range(0, final_len, Session.BUFF_SIZE):
data_list.append(tmp_data[i : i + Session.BUFF_SIZE])
return data_list
调用:
data_list = self.__preprocess_send_data(data)
for sub_data in data_list:
self.__socket.send(sub_data)
接收方:接收到长度为1024的字符串,找到第一个‘\0’字符出现的位置,此位置之前的为有效串。
def __preprocess_recv_data(self, data):
index = data.find(Session.TAG_STR)
return data[0:index]
调用:
data = self.__socket.recv(Session.BUFF_SIZE)
if data:
data = self.__preprocess_recv_data(data)
2. 在发送数据末尾加上特殊标识,接收方在接收到数据时,需要判断当前数据是否包含了特殊标记,如果包含了,则特殊标记之前的字符串为有效的一次数据记录。否则,存储起来,直到后续碰到特殊标记。
发送方:send(data + 特殊标记串)
接收方:
valid_str = "" # 有效的待处理字符串
last_left = "" # 上一次留下来的待处理串
while True:
data = self.__socket.recv(Session.BUF_SIZE)
index = data.find(特殊字符串)
if index >= 0:
valid_str = last_left + data[0:index]
last_left = data[index + len(特殊字符串):]
else:
valid_str = ""
last_left += data
if len(valid_str) > 0:
# 处理
两种方案的比较:
方案1增加了通信带宽,但容易使用和理解;
方案2节约了通信带宽,对于接收方来说,计算逻辑会更复杂。对于带宽要求较高的场景,建议用方案2.