Sie müssen einen Selektor verwenden. Zuerst eine Selector erstellen, um die Ereignisse zu empfangen:
Selector selector = Selector.open()
Dann müssen Sie die ServerSocketChannel mit dem Wahlregister:
SelectionKey acceptKey = server.register(selector, SelectionKey.OP_ACCEPT);
Dann müssen Sie den Selector verwenden, um Ereignisse zu verarbeiten, wie sie kommen in (Sie denken kann dies als „Callback“ Teil des Prozesses:
while(true){
//how many channel keys are available
int available = selector.select();
//select is blocking, but should only return if available is >0, this is more of a sanity check
if(available == 0) continue;
Iterator<SelectionKey> keys = selector.selectedKeys().iterator();
while(keys.hasNext()){
SelectionKey key = keys.next();
keys.remove();
//someone is trying to connect to the server socket
if(key.isAcceptable()) doAccept(key);
//someone is sending us data
else if(key.isReadable()) doRead(key);
//we are trying to (and can) send data
else if(key.isWritable()) doWrite(key);
}
das Fleisch in doAccept sein wird(), doRead() und doWrite() Für eine Auswahltaste Taste akzeptieren die inf enthalten. um den neuen Socket zu erstellen.
doAccept(SelectionKey key){
//create the new socket
SocketChannel socket = ((ServerSocketChannel)key.channel()).accept();
//make it non-blocking as well
socket.configureBlocking(false);
...
//here you would likely have some code to init your game objects/communication protocol, etc. and generate an identifier object (used below).
//and be able to find the socket created above
...
//Since it is non blocking it needs a selector as well, and we register for both read and write events
SelectionKey socketKey = socket.register(selector, SelectionKey.OP_READ|SelectionKey.OP_WRITE);
// so we can identify the events as they come in
socketKey.attach(someSocketIndentifier);
}
Die letzte Zeile fügt den Schlüssel einen Gegenstand so, dass die Ereignisse vom Selektor empfangen können auf eine Verbindung zurückgeführt werden (zum Beispiel könnte es ein Spieler im Spiel sein). Jetzt können Sie neue Verbindungen akzeptieren und Sie müssen nur lesen und schreiben.
doRead(SelectionKey key){
//here we retrieve the key we attached earlier, so we now what to do/wheer the data is coming from
MyIdentifierType myIdentifier = (MyIdentifierType)key.attachment();
//This is then used to get back to the SocketChannel and Read the Data
myIdentifier.readTheData();
}
in ähnlicher Weise für Schreib
doWrite(SelectionKey key){
//here we retrieve the key we attached earlier, so we now what to do/wheer the data is coming from
MyIdentifierType myIdentifier = (MyIdentifierType)key.attachment();
//This is then used to get back to the SocketChannel and Read the Data
myIdentifier.getSocketHandler().writePendingData();
}
Lesen ist ziemlich einfach, man muss nur ein ByteBuffer erstellen und rufen Sie dann die SocketChannels lesen (ByteBuffer) (oder einer seiner Varianten) die Daten zu erhalten, bereit, sich auf der Kanal bis er leer ist.
Schreiben ist ein bisschen schwieriger, wie Sie in der Regel die Daten geschrieben werden sollen, puffern wollen, bis Sie das Schreibereignis empfangen:
class MyNetworkClass{
ByteBuffer writeBuffer = ByteBuffer.allocate(1024);
SocketChannel commchannel; //from the server accept processing
...
public void write(byte[] data){
//here the class writeBuffer object is filled with the data
//but it isn't actually sent over the socket
...
}
public void writePendingData(){
//here actually write the data to the socket
commchannel.write(writeBuffer);
}
}
Beachten Sie, dass Sie über die entsprechenden Code verwalten den Puffer in der Klasse müssen in Das Ereignis wird voll, oder es wird in der Write Pending-Methode entsprechend geändert, wenn nicht alle Daten im Puffer in den Socket geschrieben werden, sowie die verschiedenen Ausnahmen, die während des Prozesses ausgelöst werden können. Hoffe, das hilft dir beim Einstieg.
Ich schlage vor, dass Sie mehrere Thread anstelle von nicht blockierenden E/A verwenden. –