TCP / IP是基于 流的 协议,而不是基于 消息的 协议。不能保证send()
一个对等方的每个呼叫都会导致另一对等方的单个recv()
呼叫接收到发送的确切数据recv()
,由于数据包分段,它可能会接收到数据块,并分成多个呼叫。
您需要在TCP之上定义自己的基于消息的协议,以区分消息边界。然后,要阅读消息,请继续呼叫recv()
直到您阅读了整个消息或发生错误为止。
发送消息的一种简单方法是为每个消息加上前缀。然后要读取一条消息,您首先要读取长度,然后读取那么多字节。您可以按照以下方式进行操作:
def send_msg(sock, msg):
# Prefix each message with a 4-byte length (network byte order)
msg = struct.pack('>I', len(msg)) + msg
sock.sendall(msg)
def recv_msg(sock):
# Read message length and unpack it into an integer
raw_msglen = recvall(sock, 4)
if not raw_msglen:
return None
msglen = struct.unpack('>I', raw_msglen)[0]
# Read the message data
return recvall(sock, msglen)
def recvall(sock, n):
# Helper function to recv n bytes or return None if EOF is hit
data = bytearray()
while len(data) < n:
packet = sock.recv(n - len(data))
if not packet:
return None
data.extend(packet)
return data
然后,您可以使用send_msg
和recv_msg
函数来发送和接收整个消息,并且它们不会对数据包在网络级别被拆分或合并产生任何问题。