Java Language
NIO - Netwerken
Zoeken…
Opmerkingen
SelectionKey
definieert de verschillende selecteerbare bewerkingen en informatie tussen de selector en het kanaal . In het bijzonder kan de bijlage worden gebruikt om verbindingsgerelateerde informatie op te slaan.
Het gebruik van OP_READ
is vrij eenvoudig. Voorzichtigheid is echter OP_WRITE
bij het omgaan met OP_WRITE
: meestal kunnen gegevens naar sockets worden geschreven, zodat het evenement blijft vuren. Zorg ervoor dat u OP_WRITE
alleen registreert voordat u gegevens wilt schrijven (zie dat antwoord ).
OP_CONNECT
moet ook worden geannuleerd zodra het kanaal is verbonden (omdat het goed is aangesloten. Zie dit en dat antwoordt op SO). Daarom is de OP_CONNECT
verwijdering na finishConnect()
geslaagd.
Selector gebruiken om te wachten op gebeurtenissen (bijvoorbeeld met OP_CONNECT)
NIO verscheen in Java 1.4 en introduceerde het concept "Kanalen", die verondersteld worden sneller te zijn dan reguliere I / O. Wat het netwerk betreft, is het SelectableChannel
het meest interessant omdat het verschillende toestanden van het kanaal kan volgen. Het werkt op dezelfde manier als de systeemaanroep C select()
: we worden wakker wanneer bepaalde soorten gebeurtenissen optreden:
- verbinding ontvangen (
OP_ACCEPT
) - verbinding gerealiseerd (
OP_CONNECT
) - gegevens beschikbaar in gelezen FIFO (
OP_READ
) - gegevens kunnen worden gepusht om FIFO te schrijven (
OP_WRITE
)
Het maakt scheiding mogelijk tussen het detecteren van socket I / O (iets kan worden gelezen / geschreven / ...) en het uitvoeren van de I / O (lezen / schrijven / ...). In het bijzonder kan alle I / O-detectie worden gedaan in een enkele thread voor meerdere sockets (clients), terwijl het uitvoeren van I / O kan worden afgehandeld in een thread-pool of ergens anders. Daardoor kan een toepassing eenvoudig worden geschaald naar het aantal verbonden clients.
Het volgende voorbeeld toont de basis:
- Maak een
Selector
- Maak een
SocketChannel
- Registreer het
SocketChannel
bij deSelector
- Lus met de
Selector
om gebeurtenissen te detecteren
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");
Zou de volgende output geven:
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