Sono un po 'turbato dal fatto che questo non possa essere gestito in modo elegante, dopo aver provato diverse soluzioni (this, this e diverse altre) menzionato nelle risposte a diverse domande SO, non riesco ancora a rilevare la disconnessione socket (scollegando il cavo) .Rilevamento della disconnessione della presa?
Sto usando il socket NIO non bloccante, tutto funziona perfettamente tranne che non trovo alcun modo di rilevare la disconnessione del server.
Ho il seguente codice:
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();
}
}
}
Mentre i SocketChannels vengono letti, ho scollegare il cavo, e Selector.select()
inizia filatura e ritorno 0, ora non ho alcuna possibilità di leggere o scrittura i canali, perché il codice di scrittura principale & è protetto da if (selectedNum > 0)
, ora questa è la prima confusione che esce dalla mia testa, da this answer, si dice che quando il canale è rotto, select() restituirà, e la selezione chiave per il canale indicherà leggibile/scrivibile, ma a quanto pare non è il caso qui, le chiavi non sono selezionati, select()
restituisce comunque 0.
Inoltre, da EJP's answer a una domanda simile:
Se il peer chiude la presa:
- read() restituisce -1
- readLine() restituisce null
- readXXX() thr OWS EOFException, per qualsiasi altro X.
Non è il caso nemmeno qui, ho provato commentando if (selectedNum > 0)
e utilizzando selector.keys().iterator()
per ottenere tutte le chiavi a prescindere o meno sono selezionati, la lettura da quelle chiavi non ritorna -1 (0 restituito invece), e la scrittura su quei tasti non ottiene EOFException
generata. Ho notato solo una cosa, che anche i tasti non sono selezionati, key.isReadable()
restituisce true mentre key.isWritable()
restituisce false (suppongo che ciò potrebbe essere dovuto al fatto che non ho registrato i tasti per OP_WRITE).
La mia domanda è perché il socket Java si comporta in questo modo o c'è qualcosa che ho fatto di sbagliato?
È possibile che il sistema operativo non dichiari ancora la connessione interrotta: è possibile ricollegare il cavo e in teoria è possibile riprendere la connessione. – MvG
Sì, a volte la connessione può essere ripristinata quando ho ricollegato il cavo, a volte 'select()' ha continuato a restituire 0 e non posso cancellare la chiave manualmente. – neevek