以下代码在 Windows 上无法正常工作(但在 Linux 上可以):
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setblocking(True)
sock.connect(address)
gobject.io_add_watch(
sock.fileno(),
gobject.IO_OUT | gobject.IO_ERR | gobject.IO_HUP,
callback)
glib 源代码中各个地方的注释片段以及其他地方提到在 Windows 中,套接字在轮询期间处于非阻塞模式。结果,回调self.outgoing_cb
被不断调用,并且写入套接字失败并显示以下错误消息:
[Errno 10035] A non-blocking socket operation could not be completed immediately
在写作之前打电话sock.setblocking(True)
似乎并没有规避这一点。通过降低轮询的优先级并忽略错误消息,它可以按预期工作,但会引发很多事件,并消耗大量 CPU。有没有办法绕过 Windows 中的这个限制?
更新
我可能会指出,轮询的全部意义POLLOUT
在于,当您进行 write 调用时,您将不会得到EAGAIN
/ EWOULDBLOCK
。我收到的奇怪错误消息,我相信这将是这两个错误代码的 Windows 等效项。换句话说,gobject.IO_OUT
当套接字不允许我成功写入时,我会收到事件,并且将其置于阻塞模式仍然会给我这个不适当的错误。
另一个更新
在 Linux 上,这可以正常工作,套接字没有切换到非阻塞模式,我收到IO_OUT
, 当套接字让我在没有阻塞的情况下写入或抛出错误时。这是我最想在 Windows 下模拟/恢复的功能。
补充说明
来自man poll
:
poll() performs a similar task to select(2): it waits for one of a set
of file descriptors to become ready to perform I/O.
POLLOUT
Writing now will not block.
来自man select
:
A file descriptor is considered ready if it is possible to perform the corre‐
sponding I/O operation (e.g., read(2)) without blocking.