我正在进行套接字编程。这里服务器向连接到服务器的机器发送随机字节数。这个随机数模拟服务器也从其他地方接收数据,数据长度可能变化很大,我们不确定有多少。
我在同一台机器上运行服务器和客户端。我原以为不会丢失数据,但令我惊讶的是,我发现这里也发生了数据丢失。我一定是在我的代码中做错了什么。我试图找到但我没有发现任何可疑的东西。我只能猜测数据的长度可能是个问题,但我仍然不确定。
我首先从服务器向客户端发送消息的长度,然后发送实际的消息,这样我就可以确定我已经收到了完整的消息。
我连接到服务器 100 次,并且多次发生数据丢失。
以下是我的服务器代码:
import socket
import struct
import random as rand
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# bind the socket to a specific address and port
server_address = ('localhost', 12345)
sock.bind(server_address)
sock.listen(1)
while True:
message = "12345" * rand.randint(100000, 200000)
connection, client_address = sock.accept()
message_in_bytes=message.encode()
length = len(message_in_bytes)
print(client_address, "connected and message length is ",length)
length_bytes = struct.pack("<I", length)
connection.send(length_bytes + message_in_bytes)
connection.close()
以下是客户端代码:
import socket
import struct
def connect_server():
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_address = ('localhost', 12345)
sock.connect(server_address)
message_length_bytes=sock.recv(4)
length_of_message = struct.unpack("<I",message_length_bytes)[0]
whole_message=sock.recv(length_of_message)
sock.close()
if length_of_message == len(whole_message):
return "success"
else:
return "failed"
stats={'success':0,'failed':0}
for _ in range(100):
stats[connect_server()] +=1
print(stats)
那么问题就出在发送的长度上。
您的消息长度最多可达 1 000 000 字节。它将超过内核缓冲区的长度。
在这种情况下,send() 返回实际传输到缓冲区的长度,您必须为额外部分重新执行 send()。
我在我的机器上做了一个测试。消息长度为 542610 但发送(0 返回 524288(512KiB)。
您必须循环 send() 直到所有内容都传输到内核缓冲区。
rand = rand.randint( 100000,200000)
length_bytes = struct.pack("<I", rand * 5)
whole_message = length_bytes + ('12345' * rand).encode()
actual_length = 0
while actual_length < len( whole_message:
nb = send( whole_message[actual_length:])
actual_length += nb
'''
Note: the length of kernel buffer may be different with your distrib.