2016-11-18 12 views
1

我正在用Python3寫一個簡單的多線程聊天服務器。有時我想中斷另一個正在等待socket.recv()的線程,以允許其執行清理任務。如何從Python的另一個線程下拉一個套接字?

從另一個線程調用socket.shutdown(socket.SHUT_RDWR)安全嗎?

+0

您可能想查看[select()](https://docs.python.org/3/library/select.html)然後,您可以監聽多個輸入並選擇準備好提供給您的數據。 – TemporalWolf

+0

@TemporalWolf我知道選擇器。不幸的是,這是一項家庭作業,我們必須使用多線程原始套接字。 – kinokijuf

+0

[This answer](http://stackoverflow.com/a/27790293/1005379)和[This one](http://stackoverflow.com/a/8050401/1005379)似乎表明這實際上是推薦的方式,但我不知道它是如何工作在一個高級語言,如Python – kinokijuf

回答

2

從另一個線程調用socket.shutdown是相當安全的,並且,作爲@kinokikuf提到的,是終止在另一個線程阻塞recv()以適當的方式,只要你能保證插座還沒有結束的時候調用shutdown()發生。

如果您無法保證套接字尚未關閉,那麼在調用shutdown時可能會遇到異常,或者如果發生競態條件並且套接字句柄被操作系統重用,您甚至可能會終止另一個無關的連接!

Linux man pageshutdown()系統調用沒有明確說明,阻斷的recv()調用將被終止,僅表示「進一步接收和發送將被禁止」。但實際上,這似乎包括在Unixoid系統和Windows上的同一個套接字上阻塞recv()調用。

另一種方法是使用socket.settimeout()來規避不確定的阻塞問題,並定期檢查線程內部(如全局變量)是否應該關閉連接。

中斷recv()的另一個合理的方法是向線程發送一個非致命的信號,這會中斷recv()系統調用,但似乎沒有用於低級別函數的包裝函數Python和自Python 3.5 system calls will be automatically restarted if interrupted,這使得這個選項不可用。

+0

謝謝!我只是從管理函數的線程調用close(),所以我總是關閉一個打開的套接字。 – kinokijuf