2010-05-19 78 views
14

我想使用SocketChannel並有其讀/寫方法超時。我試圖設置超時爲擁有我SocketChannel這樣的插座:超時的SocketChannel不起作用

channel.socket().setSoTimeout(TIMEOUT); 

,但不起作用。還有其他解決方案嗎?

+3

不幸的是,SocketChannel不直接支持setSoTimeout方法。使用它將會被遺忘。 – casey 2011-03-26 18:29:55

+5

SocketChannel實現了InterruptibleChannel接口,這意味着您可以在進入read()調用之前創建一個單獨的線程,讓其他線程設置一個計時器,並且在計時器到期時,它可能會中斷SocketChannel讀取的線程()呼叫被阻止。如果read()調用首先返回,那麼可以讓它終止計時器線程。 – 2012-02-03 01:41:09

+4

@StevensMiller通道將被關閉,讀取將拋出'ClosedByInterruptException.'不是很有用。我被告知這種奇怪的實現是由Linux的行爲強制的。 – EJP 2015-02-08 22:32:57

回答

14

根據此article,SocketChannel將不會超時讀取操作,但您可以通過另一種方式從通道中讀取此效果。

SocketChannel socketChannel; 
socketChannel.socket().setSocketTimeout(500); 
InputStream inStream = socketChannel.socket().getInputStream(); 
ReadableByteChannel wrappedChannel = Channels.newChannel(inStream); 

從wrappedChannel中讀取將根據您設置的socketTimeOut超時。

+0

很好的解決方案。 Java是...卡住 – 2015-09-11 06:45:36

+1

這不是正確的方法來做到這一點,只有一個解決方法。正確的方法是在一個循環中使用Selector.select(timeout),並用if if檢查soTimeout/connectTimeout – wzona 2016-10-13 10:55:52

+0

'setSocketTimeout'現在是'setSoTimeout',但工作方式相同。 – 2018-03-07 16:47:15

-1

你也可以考慮讓你的頻道不可阻擋,並使用System.currentTimeMillis()。

2

如果您熟悉使用Java Selector,則可以使用選擇器模擬套接字超時。看到sun.nio.ch.SocketAdaptor是有幫助的。

它應該小心使用Thread.interrupt()。 SocketChannel是InterruptibleChannel。在您閱讀InterruptibleChannel的描述時,Thread.interrupt()會導致關閉 SocketChannel。 如果您想在超時後使用SocketChannel,則無法使用InterruptibleChannel功能。