以下代码不正常工作上的窗户(但并在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)

片段的评论意见在各个地方的巧舌如簧源和其他地方提到,在Windows,sockets是把在非阻挡的模式在投票。结果回调 self.outgoing_cb 是不断呼吁,并写到插座失败这个错误信息:

[Errno 10035] A non-blocking socket operation could not be completed immediately

sock.setblocking(True) 之前以书面似乎没有规避这一点。通过降低优先的投票,而忽略了错误信息,它的工作不如预期,但投迄今许多事件,并且消耗了大量的CPU。有没有办法绕过这个限制在窗口?

更新

我可以指出,即整个点的投票 POLLOUT 是,当你写信呼吁你不会得到 EAGAIN/EWOULDBLOCK.奇怪的错误消息,我的,我相信将Windows相当于2个错误代码。换句话说,我得到 gobject.IO_OUT 事件当插座不会让我写成功, 把它放到阻挡的模式仍然给了我这个不恰当的错误。

另一个更新

在Linux上,这种工作是否正确,这座是不切换到非阻挡的模式,我收到 IO_OUT, 当插座让我写的没有阻止,或者投掷一个错误。这是这个功能我想最好模仿/恢复在窗。

进一步注意到

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.
有帮助吗?

解决方案

执行非阻塞 I/O 是否有问题?如果您使用阻塞 I/O,那么使用轮询循环似乎有点奇怪。

当我编写这样的程序时,我倾向于执行以下操作:

  • 缓冲我想要发送到文件描述符的字节。

  • 只求 IO_OUT (或者 poll() 相等的, POLLOUT) 当所述缓冲区非空时发生的事件。

  • 什么时候 poll() (或同等)已表明您已准备好写入,请发出写入。如果你得到 EAGAIN/EWOULDBLOCK, ,从缓冲区中删除成功写入的字节并等待下一次收到信号。如果您成功写入整个缓冲区,则停止询问 POLLOUT 这样你就不会虚假地醒来。

(我的猜测是 Win32 绑定正在使用 WSA事件选择WaitForMultipleObjects() 模拟 poll(), ,但结果是一样的......)

我不确定您想要的阻塞套接字方法如何工作。你不断地“醒来”,因为你要求在你可以写作的时候叫醒你。您只想指定当您有数据要写入时......但是,当它叫醒你时,系统不会真正告诉你 多少 您可以在不阻塞的情况下写入数据,因此这是使用非阻塞 I/O 的充分理由。

其他提示

吉奥 包含 GSocket, 一个"低级的网络插座的对象,"因为2.22.但是这尚未被移植到 pygobject on Windows.

我不知道如果这有助于(我不是精通该查询功能或MFC插座,不知道投票是你的程序结构的要求),所以借此与一粒盐:

但为了避免在写阻塞或EAGAIN,我们使用选择,即插槽添加到传递给选择写集合,如果选择()回来了RC = 0的插槽可写的时候了。 ..

我们在我们的应用程序使用的写循环是(在伪代码):

set_nonblocking.
count= 0.
do {
   FDSET writefds;
   add skt to writefds.
   call select with writefds and a reaonsable timeout.
   if (select fails with timeout) {
       die with some error;
   } 

   howmany= send(skt, buf+count, total-count).
   if (howmany>0) {
       count+= howmany.
   }
} while (howmany>0 && count<total);

你可以用 扭曲的, ,其中包括 支持GTK (甚至在窗户),并将处理所有的 各个 错误的条件,不阻止插座上的窗户喜欢的提高。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top