我正在用Python3寫一個簡單的多線程聊天服務器。有時我想中斷另一個正在等待socket.recv()的線程,以允許其執行清理任務。如何從Python的另一個線程下拉一個套接字?
從另一個線程調用socket.shutdown(socket.SHUT_RDWR)安全嗎?
我正在用Python3寫一個簡單的多線程聊天服務器。有時我想中斷另一個正在等待socket.recv()的線程,以允許其執行清理任務。如何從Python的另一個線程下拉一個套接字?
從另一個線程調用socket.shutdown(socket.SHUT_RDWR)安全嗎?
從另一個線程調用socket.shutdown
是相當安全的,並且,作爲@kinokikuf提到的,是終止在另一個線程阻塞recv()
以適當的方式,只要你能保證插座還沒有結束的時候調用shutdown()
發生。
如果您無法保證套接字尚未關閉,那麼在調用shutdown時可能會遇到異常,或者如果發生競態條件並且套接字句柄被操作系統重用,您甚至可能會終止另一個無關的連接!
的Linux man page爲shutdown()
系統調用沒有明確說明,阻斷的recv()調用將被終止,僅表示「進一步接收和發送將被禁止」。但實際上,這似乎包括在Unixoid系統和Windows上的同一個套接字上阻塞recv()
調用。
另一種方法是使用socket.settimeout()來規避不確定的阻塞問題,並定期檢查線程內部(如全局變量)是否應該關閉連接。
中斷recv()
的另一個合理的方法是向線程發送一個非致命的信號,這會中斷recv()系統調用,但似乎沒有用於低級別函數的包裝函數Python和自Python 3.5 system calls will be automatically restarted if interrupted,這使得這個選項不可用。
謝謝!我只是從管理函數的線程調用close(),所以我總是關閉一個打開的套接字。 – kinokijuf
您可能想查看[select()](https://docs.python.org/3/library/select.html)然後,您可以監聽多個輸入並選擇準備好提供給您的數據。 – TemporalWolf
@TemporalWolf我知道選擇器。不幸的是,這是一項家庭作業,我們必須使用多線程原始套接字。 – kinokijuf
[This answer](http://stackoverflow.com/a/27790293/1005379)和[This one](http://stackoverflow.com/a/8050401/1005379)似乎表明這實際上是推薦的方式,但我不知道它是如何工作在一個高級語言,如Python – kinokijuf