如果发件人发送得太快,我的客户端将无法接收这两条消息。
sender.py
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind(('', int(port)))
sock.listen(1)
conn, addr = sock.accept()
#conn.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
# sends message 1 and message 2
conn.send(pickle.dumps(message1))
#time.sleep(1)
conn.send(pickle.dumps(message2))
消息1和消息2均为腌制对象。
client.py
sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
sock.connect((ip,int(port)))
message1 = pickle.loads(sock.recv(1024))
print(message1)
message2 = pickle.loads(sock.recv(1024))
按原样运行此代码时,我可以打印出message1,但无法从发件人接收message2。套接字在message2处阻塞。
此外,如果我在发件人附带的代码中取消注释time.sleep(1),我将能够很好地接收两条消息。不确定是什么问题。我试图每次通过设置TCP_NODELAY来刷新我的TCP缓冲区,但这没有用。不知道实际发生了什么?我如何确保我收到两条消息
答案 0 :(得分:1)
您的代码假设服务器端的每个send
与客户端端的recv
相匹配。但是,TCP是字节流,而不是基于消息的协议。这意味着您的第一个recv
很可能已经包含了第二个send
的数据,这些数据可能被pickle.loads
丢弃,成为腌制数据之后的垃圾。第二个recv
将仅接收剩余数据(或由于已接收所有数据而仅阻塞),因此pickle.loads
将失败。
处理这种情况的常用方法是在TCP字节流的顶部构造一个消息协议。例如,这可以通过以下方式来实现:在发送时为每条消息添加固定长度的前缀(例如,使用struct.pack('L',...)
作为4字节uint),并为读取而首先读取固定长度的值,然后使用给定大小。