下面的代碼不能在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)
片段的在各個地方的意見在巧舌如簧源,和其他地方提到,在Windows中,套接字在輪詢期間處於非阻塞模式。因此回調self.outgoing_cb
的不斷呼籲,並寫入套接字失敗,出現此錯誤消息:
[Errno 10035] A non-blocking socket operation could not be completed immediately
調用事先書面sock.setblocking(True)
來似乎並不迴避這一點。通過降低投票的優先級,並忽略錯誤信息,它按預期工作,但遠遠拋出很多事件,並消耗大量的CPU。在Windows中有沒有辦法解決這個限制?
更新
我可能會指出,該輪詢POLLOUT
的整點是,當你寫叫你不會得到EAGAIN
/EWOULDBLOCK
。奇怪的錯誤消息,我得到的,我相信會是Windows平臺上類似的2個錯誤代碼。換句話說,我越來越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.
關於你從手冊中引用的內容:它不會阻塞一定數量的字節,是正確的。但是......在成功運營的最後階段,您仍然可以獲得EAGAIN。它並沒有告訴你這些字節是多少。因此,對這些事件之一的適當反應是成功讀取或寫入儘可能多的數據,然後在用盡該數字時獲取EAGAIN(也稱爲EWOULDBLOCK)。 – asveikau 2009-11-21 00:55:27
@asveikau:EAGAIN僅適用於非阻塞套接字。如果select()返回阻塞套接字已準備好寫入,它將立即接收儘可能多的字節並返回該數字。 – 2009-11-21 02:23:34
@Anacrolix我認爲我們在這裏討論write()。如果你在阻塞套接字上選擇(),並且它告訴你是時候寫了,那麼你的write()比可以立即發送的更多,它會被阻塞。此外,在閱讀的案例中,既然你提到它......首先我不認爲你寫的是真的。但假設它是......你怎麼知道可以讀的上限?只需傳入一個大緩衝區?這沒有意義。最好在循環中讀取(),而不要受到任意大小的限制。 – asveikau 2009-11-21 03:59:18