在 TCP 套接字连接中丢失数据

问题描述 投票:0回答:1

我正在进行套接字编程。这里服务器向连接到服务器的机器发送随机字节数。这个随机数模拟服务器也从其他地方接收数据,数据长度可能变化很大,我们不确定有多少。

我在同一台机器上运行服务器和客户端。我原以为不会丢失数据,但令我惊讶的是,我发现这里也发生了数据丢失。我一定是在我的代码中做错了什么。我试图找到但我没有发现任何可疑的东西。我只能猜测数据的长度可能是个问题,但我仍然不确定。

我首先从服务器向客户端发送消息的长度,然后发送实际的消息,这样我就可以确定我已经收到了完整的消息。

我连接到服务器 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)
python sockets
1个回答
0
投票

那么问题就出在发送的长度上。 您的消息长度最多可达 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.
  
© www.soinside.com 2019 - 2024. All rights reserved.