我有點不高興,因爲在嘗試不同的解決方案(this,this和其他幾個)在幾個SO問題的答案中提到不同的解決方案後,我仍然無法設法檢測套接字斷開(通過拔下電纜) 。檢測套接字斷開?
我正在使用NIO非阻塞套接字,除了找不到檢測服務器斷開連接的方法之外,一切都很完美。
我有以下代碼:
while (true) {
handlePendingChanges();
int selectedNum = selector.select(3000);
if (selectedNum > 0) {
SelectionKey key = null;
try {
Iterator<SelectionKey> keyIterator = selector.selelctedKeys().iterator();
while (keyIterator.hasNext()) {
key = keyIterator.next();
if (!key.isValid())
continue;
System.out.println("key state: " + key.isReadable() + ", " + key.isWritable());
if (key.isConnectable()) {
finishConnection(key);
} else if (key.isReadable()) {
onRead(key);
} else if (key.isWritable()) {
onWrite(key);
}
}
} catch (Exception e) {
e.printStackTrace();
System.err.println("I am happy that I can catch some errors.");
} finally {
selector.selectedKeys().clear();
}
}
}
當正在讀SocketChannels,我拔掉數據線,並Selector.select()
開始旋轉並返回0,現在我已經沒有機會閱讀或寫因爲主要讀取&的編寫代碼是由守衛if (selectedNum > 0)
,現在這是第一個混淆出來的我的頭,從this answer,據說當頻道壞了,select()會返回,而選擇關鍵信道將指示讀/寫,但它顯然不是這裏的情況下,該鍵沒有被選擇,select()
仍然返回0
此外,從EJP's answer到一個類似的問題:
如果對等關閉套接字:
- read()返回-1
- 的readLine()返回null
- 的readXXX()THR OWS EOFException類,任何其他X上
不在這裏要麼這樣,我試着註釋掉if (selectedNum > 0)
使用selector.keys().iterator()
讓所有的鑰匙,無論他們是否被選中,從這些密鑰讀取不回-1(0代替),寫入這些鍵不會得到EOFException
拋出。我只注意到一件事,即使沒有選擇鍵,key.isReadable()
返回true,而key.isWritable()
返回false(我猜這可能是因爲我沒有註冊OP_WRITE的鍵)。
我的問題是爲什麼Java套接字的行爲是這樣或有什麼我做錯了?
可能是操作系統不聲明連接斷開:您可能會重新插入電纜,理論上連接可能會恢復。 – MvG
是的,有時當我插入電纜時,連接可能會恢復,有時'select()'只是一直返回0,我不得不手動取消鍵。 – neevek