带有while循环的Recvall在python中的两个设备之间不起作用

Posted

技术标签:

【中文标题】带有while循环的Recvall在python中的两个设备之间不起作用【英文标题】:Recvall with while loop doesn't work between two devices in python 【发布时间】:2021-10-02 11:50:35 【问题描述】:

我有以下问题:我想要一个服务器来发送一个文本文件的内容 当被要求这样做时。我编写了一个服务器脚本,它将内容发送到客户端,客户端脚本通过 revcall 循环接收所有内容。 recvall 工作正常时 我从同一台设备运行服务器和客户端进行测试。 但是当我从同一个 wifi 网络中的不同设备运行服务器以从服务器设备接收文本文件内容时,recvall 不起作用,我只接收到文本的前 1460 个字节。

服务器脚本

import socket

server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(("", 5000))
server.listen(5)


def send_file(client):
    read_string = open("textfile", "rb").read()  #6 kilobyte large textfile
    client.send(read_string)


while True:
    client, data = server.accept()
    connect_data = client.recv(1024)
    if connect_data == b"send_string":
        send_file(client)
    else:
        pass

客户端脚本

import socket

client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect(("192.168.1.10", 5000))

connect_message = client.send(b"send_string")

receive_data = ""
while True:                                        # the recvall loop
    receive_data_part = client.recv(1024).decode()
    receive_data += receive_data_part
    if len(receive_data_part) < 1024:
        break

print(receive_data)

【问题讨论】:

您应该使用.sendall() 而不是.send(),尤其是在发送大量数据时。另一种方法是检查.send() 的返回值,如果没有处理整个字符串,则重试。 您可以接收从 1 到 1024 字节的任何内容。在机器之间,您的数据被分段有点不同,并且您收到部分 您的协议需要某种方式让接收方知道传输何时完成。这可能是关闭套接字,在数据之前发送总长度值,或者某种结束标记,例如 NULL 值。 (例如,http 连续使用两个换行符)。有很多方法可以解决这个问题。 顺便说一句,服务器也有同样的问题。无法保证您会在单个 recv 缓冲区中准确收到 b"send_string" 【参考方案1】:

recv(1024) 表示接收至少 1 且最多 1024 个字节。如果连接已关闭,您会收到 0 个字节,如果出现问题,您会收到异常。

TCP 是一个字节流。它不会尝试将来自任何给定send 的字节保留在recv 中。当你进行调用时,如果 TCP 端点有一些数据,你就会得到这些数据。

在客户端中,您假设任何小于 1024 字节的数据都必须是最后一位数据。不是这样。您可以随时接收部分缓冲区。它在服务器端有点微妙,但你会犯同样的错误,假设你会在一次调用中准确地收到命令b"send_string"

您需要某种协议来告诉接收者何时获得了正确数量的数据以执行某项操作。有很多方法可以做到这一点,所以我不能真正给你答案。但这就是为什么会有诸如 zeromq、xmlrpc、http 等协议的原因......

【讨论】:

以上是关于带有while循环的Recvall在python中的两个设备之间不起作用的主要内容,如果未能解决你的问题,请参考以下文章

如何结束带有 for 循环的 while 循环?

在 NodeJS 中使用带有 SQL 请求的 While 循环

如何在while循环中读取带有空格的字符串(Java)

在带有条件语句的 while 循环中放置错误消息

带有条件的 Bash 单行 while 循环的语法

带有字符串而不是整数的 while 循环