Java Language
NIO - sieć
Szukaj…
Uwagi
SelectionKey
definiuje różne operacje i informacje do wyboru między Selektorem a Kanałem . W szczególności załącznik może służyć do przechowywania informacji związanych z połączeniem.
Obsługa OP_READ
jest bardzo prosta. Należy jednak zachować ostrożność podczas obsługi OP_WRITE
: przez większość czasu dane mogą być zapisywane w gniazdach, aby zdarzenie było kontynuowane. Pamiętaj, aby zarejestrować OP_WRITE
tylko przed zapisaniem danych (zobacz tę odpowiedź ).
Również OP_CONNECT
powinien zostać anulowany po połączeniu kanału (ponieważ, no cóż, jest podłączony. Zobacz to i to odpowiedzi na SO). Stąd usunięcie OP_CONNECT
po finishConnect()
zakończeniu finishConnect()
.
Używanie Selektora do oczekiwania na zdarzenia (przykład z OP_CONNECT)
NIO pojawiło się w Javie 1.4 i wprowadziło koncepcję „kanałów”, które mają być szybsze niż zwykłe wejścia / wyjścia. Jeśli chodzi o sieć, kanał SelectableChannel
jest najbardziej interesujący, ponieważ pozwala monitorować różne stany kanału. Działa w podobny sposób jak wywołanie systemowe C select()
: budzimy się, gdy wystąpią określone typy zdarzeń:
- połączenie otrzymane (
OP_ACCEPT
) - połączenie zrealizowane (
OP_CONNECT
) - dane dostępne w odczycie FIFO (
OP_READ
) - dane mogą być wypychane do zapisu FIFO (
OP_WRITE
)
Pozwala na separację między wykrywaniem We / Wy gniazda (coś można odczytać / zapisać / ...) a wykonaniem We / Wy (odczyt / zapis / ...). W szczególności wszystkie wykrywanie we / wy można wykonać w jednym wątku dla wielu gniazd (klientów), podczas gdy wykonywanie we / wy może być obsługiwane w puli wątków lub gdziekolwiek indziej. Pozwala to aplikacji łatwo skalować do liczby podłączonych klientów.
Poniższy przykład pokazuje podstawy:
- Utwórz
Selector
- Utwórz
SocketChannel
- Zarejestruj
SocketChannel
wSelector
- Pętla z
Selector
do wykrywania zdarzeń
Selector sel = Selector.open(); // Create the Selector
SocketChannel sc = SocketChannel.open(); // Create a SocketChannel
sc.configureBlocking(false); // ... non blocking
sc.setOption(StandardSocketOptions.SO_KEEPALIVE, true); // ... set some options
// Register the Channel to the Selector for wake-up on CONNECT event and use some description as an attachement
sc.register(sel, SelectionKey.OP_CONNECT, "Connection to google.com"); // Returns a SelectionKey: the association between the SocketChannel and the Selector
System.out.println("Initiating connection");
if (sc.connect(new InetSocketAddress("www.google.com", 80)))
System.out.println("Connected"); // Connected right-away: nothing else to do
else {
boolean exit = false;
while (!exit) {
if (sel.select(100) == 0) // Did something happen on some registered Channels during the last 100ms?
continue; // No, wait some more
// Something happened...
Set<SelectionKey> keys = sel.selectedKeys(); // List of SelectionKeys on which some registered operation was triggered
for (SelectionKey k : keys) {
System.out.println("Checking "+k.attachment());
if (k.isConnectable()) { // CONNECT event
System.out.print("Connected through select() on "+k.channel()+" -> ");
if (sc.finishConnect()) { // Finish connection process
System.out.println("done!");
k.interestOps(k.interestOps() & ~SelectionKey.OP_CONNECT); // We are already connected: remove interest in CONNECT event
exit = true;
} else
System.out.println("unfinished...");
}
// TODO: else if (k.isReadable()) { ...
}
keys.clear(); // Have to clear the selected keys set once processed!
}
}
System.out.print("Disconnecting ... ");
sc.shutdownOutput(); // Initiate graceful disconnection
// TODO: emtpy receive buffer
sc.close();
System.out.println("done");
Dałby następujące dane wyjściowe:
Initiating connection
Checking Connection to google.com
Connected through 'select()' on java.nio.channels.SocketChannel[connection-pending remote=www.google.com/216.58.208.228:80] -> done!
Disconnecting ... done