Python套接字:发送和接收16字节

4

请参见下方的编辑。

我有两个通过套接字通信的程序。我试图从一个程序发送一块数据到另一个程序。这在使用某些测试数据时可以正常工作,但在使用其他数据时失败了。

s.sendall('%16d' % len(data))
s.sendall(data)
print(len(data))

发送到
size = int(s.recv(16))
recvd = ''
while size > len(recvd):
    data = s.recv(1024)
    if not data: 
        break
    recvd += data
print(size, len(recvd))

在一端:

s = socket.socket()
s.connect((server_ip, port))

以及另一个:

c = socket.socket()
c.bind(('', port))
c.listen(1)
s,a = c.accept()

在我的最新测试中,我发送了一个7973903字节的数据块,但接收方报告大小为7973930。
为什么接收的数据块会差27个字节?
还有其他问题吗?
Python版本为2.7或2.5.4(如果有关系)。
编辑:啊哈——我可能读取了发送缓冲区的末尾。如果剩余字节数小于1024,则只需读取剩余字节数。这种数据传输有标准技术吗?我感觉我在重新发明轮子。
编辑2:我犯了错误,读取了系列中的下一个文件。我正在发送file1,最后一个块是997个字节。然后我发送file2,所以在file1末尾的recv(1024)读取file2的前27个字节。
我将在另一个问题上开始如何更好地处理这个问题。
谢谢大家。 提问和阅读评论帮助我集中注意力。

"repr()不起作用?" 它并不是为了“帮助”。它的作用是生成输出,以便您可以将其添加到问题中,以便我们可以看到实际接收器实际读取的整个16字节。它不会“修复”任何东西。它是用于诊断问题的。请收集我们要求的输出,并更新问题,以显示实际输出。 - S.Lott
@Jingshao: 问题是我正在读取传输的下一个数据块。这是二进制数据。 - foosion
@S.Lott:repr()并没有帮助,因为它不会透露比print更多的信息。 - foosion
还有一个问题,客户端和服务器在同一台机器上吗?可能是网络问题吗?这种情况每次都发生吗? - Jingshao Chen
7
了解,如果您已经找到了答案,那么您应该在自己的问题下发布答案并接受它,这样就不会再被标记为未回答了 :-) - Hamy
显示剩余9条评论
1个回答

2

首先,这行代码

size = int(s.recv(16))

可能读取的字节数少于16个字节——虽然不太可能,但取决于网络缓冲区的对齐方式是有可能的。 recv() 调用的参数是一个最大值,即您愿意接收的数据量上限。但您可能只会接收到一个字节。一旦至少有一个字节到达,操作系统通常会将控制权交还给您,也许(根据操作系统和CPU的繁忙程度)在等待另一个包含更多数据的第二个数据包到达时再等待几毫秒,以便它只需要唤醒您一次而不是两次。

因此,您应该这样说(执行最简单的循环; 其他变体也可能):

data = ''
while len(data) < 16:
    more = s.recv(16 - len(data))
    if not more:
        raise EOFError()
    data += more

这确实是一个几乎每个人都需要重新发明的轮子,因为它经常被需要。而且你自己的代码也需要它第二次:你的while循环需要它的recv()来倒数,要求越来越小的限制,直到最终收到承诺的确切字节数,没有更多。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接