Java NIO - ServerSocket Channel

Il canale socket del server Java NIO è di nuovo un canale di tipo selezionabile utilizzato per il flusso di dati orientato al flusso che collega i socket.Il canale Socket del server può essere creato invocando il suo open() , a condizione che non sia già presente un socket preesistente Il canale Socket server viene creato invocando il metodo aperto ma non ancora associato. bind() metodo deve essere chiamato.

Un punto da menzionare qui è che se il canale non è associato e si tenta di tentare qualsiasi operazione di I / O, NotYetBoundException viene generata da questo canale, quindi è necessario assicurarsi che il canale sia limitato prima di eseguire qualsiasi operazione di I / O.

Le connessioni in entrata per il canale socket del server vengono ascoltate chiamando il metodo ServerSocketChannel.accept (). Quando il metodo accept () restituisce, restituisce un SocketChannel con una connessione in entrata. Pertanto, il metodo accept () si blocca fino all'arrivo di una connessione in entrata. Se il canale è in modalità non bloccante, il metodo accept restituirà immediatamente null se non ci sono connessioni in sospeso. Altrimenti si bloccherà indefinitamente fino a quando non sarà disponibile una nuova connessione o si verificherà un errore di I / O.

Il socket del nuovo canale è inizialmente non associato; deve essere associato a un indirizzo specifico tramite uno dei metodi bind del suo socket prima che le connessioni possano essere accettate. Inoltre, il nuovo canale viene creato invocando il metodo openServerSocketChannel dell'oggetto SelectorProvider predefinito a livello di sistema.

Come il canale socket, il canale socket del server potrebbe leggere i dati utilizzando read()Per prima cosa viene allocato il buffer. I dati letti da un ServerSocketChannel vengono memorizzati nel buffer. In secondo luogo chiamiamo il metodo ServerSocketChannel.read () e leggiamo i dati da un ServerSocketChannel in un buffer. Il valore intero del metodo read () restituisce quanti byte sono stati scritti nel buffer

Allo stesso modo i dati potrebbero essere scritti sul canale socket del server utilizzando write() metodo utilizzando buffer come parametro.Commonly utilizza il metodo write in un ciclo while in quanto è necessario ripetere il metodo write () finché il buffer non ha ulteriori byte disponibili per la scrittura.

Metodi importanti del canale Socket

  • bind(SocketAddress local) - Questo metodo viene utilizzato per associare il canale socket all'indirizzo locale fornito come parametro a questo metodo.

  • accept() - Questo metodo viene utilizzato per accettare una connessione effettuata al socket di questo canale.

  • connect(SocketAddress remote) - Questo metodo viene utilizzato per connettere la presa all'indirizzo remoto.

  • finishConnect() - Questo metodo viene utilizzato per completare il processo di connessione di un canale socket.

  • getRemoteAddress() - Questo metodo restituisce l'indirizzo della posizione remota a cui è connesso il socket del canale.

  • isConnected() - Come già accennato questo metodo restituisce lo stato di connessione del canale socket cioè se è connesso o meno.

  • open() - Il metodo Open viene utilizzato per aprire un canale socket per nessun indirizzo specificato.Questo metodo pratico funziona come se invocasse il metodo open (), invocando il metodo di connessione sul canale socket del server risultante, passandolo remoto e quindi restituendo quel canale.

  • read(ByteBuffer dst) - Questo metodo viene utilizzato per leggere i dati dal buffer specificato attraverso il canale socket.

  • setOption(SocketOption<T> name, T value) - Questo metodo imposta il valore di un'opzione socket.

  • socket() - Questo metodo recupera un socket del server associato a questo canale.

  • validOps() - Questo metodo restituisce un set di operazioni che identifica le operazioni supportate da questo canale. I canali server-socket supportano solo l'accettazione di nuove connessioni, quindi questo metodo restituisce SelectionKey.OP_ACCEPT.

Esempio

L'esempio seguente mostra come inviare dati da Java NIO ServerSocketChannel.

C: /Test/temp.txt

Hello World!

Cliente: SocketChannelClient.java

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.EnumSet;

public class SocketChannelClient {
   public static void main(String[] args) throws IOException {
      ServerSocketChannel serverSocket = null;
      SocketChannel client = null;
      serverSocket = ServerSocketChannel.open();
      serverSocket.socket().bind(new InetSocketAddress(9000));
      client = serverSocket.accept();
      System.out.println("Connection Set:  " + client.getRemoteAddress());
      Path path = Paths.get("C:/Test/temp1.txt");
      FileChannel fileChannel = FileChannel.open(path, 
         EnumSet.of(StandardOpenOption.CREATE, 
            StandardOpenOption.TRUNCATE_EXISTING,
            StandardOpenOption.WRITE)
         );      
      ByteBuffer buffer = ByteBuffer.allocate(1024);
      while(client.read(buffer) > 0) {
         buffer.flip();
         fileChannel.write(buffer);
         buffer.clear();
      }
      fileChannel.close();
      System.out.println("File Received");
      client.close();
   }
}

Produzione

L'esecuzione del client non stamperà nulla fino all'avvio del server.

Server: SocketChannelServer.java

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.SocketChannel;
import java.nio.file.Path;
import java.nio.file.Paths;

public class SocketChannelServer {
   public static void main(String[] args) throws IOException {
      SocketChannel server = SocketChannel.open();
      SocketAddress socketAddr = new InetSocketAddress("localhost", 9000);
      server.connect(socketAddr);
      Path path = Paths.get("C:/Test/temp.txt");
      FileChannel fileChannel = FileChannel.open(path);
      ByteBuffer buffer = ByteBuffer.allocate(1024);
      while(fileChannel.read(buffer) > 0) {
         buffer.flip();
         server.write(buffer);
         buffer.clear();
      }
      fileChannel.close();
      System.out.println("File Sent");
      server.close();
   }
}

Produzione

L'esecuzione del server stamperà quanto segue.

Connection Set:  /127.0.0.1:49558
File Received