为什么UDP套接字的socket.makefile对象在第一次读取后失效?
我正在使用 socket.makefile 方法,在一个UDP套接字上创建一个类似文件的对象,目的是为了读取数据。当我收到一个UDP数据包时,我可以通过使用read方法一次性读取整个数据包的内容,但如果我尝试分开多次读取,程序就会卡住。
下面是一个演示这个问题的程序:
import socket
from sys import argv
SERVER_ADDR = ("localhost", 12345)
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind(SERVER_ADDR)
f = sock.makefile("rb")
sock.sendto("HelloWorld", SERVER_ADDR)
if "--all" in argv:
print f.read(10)
else:
print f.read(5)
print f.read(5)
如果我用 --all
选项运行上面的程序,它就能正常工作,并打印出 HelloWorld
。但是如果我不加这个选项,它会先打印 Hello
,然后在第二次读取时就卡住了。我在使用TCP套接字时,使用 socket.makefile
对象没有这个问题。
这到底是为什么呢?我该怎么做才能解决这个问题?
1 个回答
2
你发送了一个数据包,但调用了两次读取操作。第二次读取不会有任何数据,因为没有新的数据包可以读取。UDP套接字的读取操作一次只能读取一个数据包,如果你没有读取完所有的字节,剩下的数据就会被丢弃。UDP不是以流的方式工作的,而是以消息或数据报的方式。
UDP和文件的概念不太一样。一个“文件”只是字节的流,而不是数据包的集合,而且它是有结尾的。就像TCP一样,你从中读取字节——你使用多少次读取来获取数据并不重要,而且你可以检测到它的结束。