Python Socket: 发送和接收16字节
请看下面的编辑内容。
我有两个程序,它们通过套接字进行通信。我想把一块数据从一个程序发送到另一个程序。用一些测试数据时,这个过程是正常的,但用其他数据时就出问题了。
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个字节。
我会再开一个问题,问问怎么做得更好。
谢谢大家。提问和阅读评论帮助我理清了思路。
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()
逐渐减少请求的字节数,直到最终准确接收到承诺的字节数,而不会多接收到任何字节。