python: 两次调用 socket.recvfrom()
我正在写两个Python脚本,通过UDP使用Python的sockets进行通信。这里是相关的代码部分:
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind((HOST, PORT))
s.setblocking(True) #I want it to be blocking
#(...)
(msg, addr) = sock.recvfrom(4)
#(...)
(msg2, addr2) = sock.recvfrom(2)
我希望接收数据时是阻塞的,也就是说在接收到数据之前,程序会停下来等着。我在读取前4个字节之前并不知道整个消息的大小。上面的代码在sock.recvfrom(2)
这一部分会被阻塞,而如果把它改成一个sock.recvfrom
,就能正常工作:
(msg, addr) = sock.recvfrom(6) #works ok, but isn't enough for my needs
有没有什么好办法可以方便地分两部分读取传入的数据,或者说说为什么我的代码没有按预期工作?
3 个回答
1
UDP是一种基于消息的协议。recvfrom
这个函数会读取最初发送的整个消息,但如果接收的缓冲区不够大,就会出现错误:
socket.error: [Errno 10040] 通过数据报套接字发送的消息比内部消息缓冲区大,或者超过了其他网络限制,或者用于接收数据报的缓冲区比数据报本身小
所以我不明白为什么在发送了一个6字节的消息后,你会在第二个recvfrom
上卡住。你应该在第一个recvfrom
上就抛出错误。也许可以提供一个实际可运行的、最简化的客户端和服务器程序的例子。
2
从UDP套接字读取时,会把整个数据包取出来。
5
socket.recvfrom(size)
这个函数用于接收UDP协议的网络数据,它会读取一个数据包,最多读取 size
字节。如果数据包里有多余的数据,这些多余的数据会被 丢弃。如果你想要接收整个数据包,就需要传入一个更大的缓冲区大小,然后再对数据包进行处理,而不是试图一部分一部分地接收。
如果你想要一个更方便、更加稳定的网络输入输出接口,可以考虑使用 Twisted。