Java NIO - Canal ServerSocket

El canal de socket del servidor Java NIO es nuevamente un canal de tipo seleccionable que se utiliza para los sockets de conexión de flujo de datos orientados al flujo. open() método, siempre que no haya ningún socket preexistente ya presente El canal del socket del servidor se crea invocando el método abierto pero aún no está vinculado. bind() se llamará al método.

Un punto que se debe mencionar aquí es que si el canal no está vinculado y se intenta realizar cualquier operación de E / S, este canal lanza NotYetBoundException, por lo que debe asegurarse de que el canal esté delimitado antes de realizar cualquier operación de E / S.

Las conexiones entrantes para el canal del socket del servidor se escuchan llamando al método ServerSocketChannel.accept (). Cuando el método accept () regresa, devuelve un SocketChannel con una conexión entrante. Por lo tanto, el método accept () se bloquea hasta que llega una conexión entrante. Si el canal está en modo sin bloqueo, el método accept devolverá inmediatamente un valor nulo si no hay conexiones pendientes. De lo contrario, se bloqueará indefinidamente hasta que haya una nueva conexión disponible o se produzca un error de E / S.

Inicialmente, el zócalo del nuevo canal no está ligado; debe estar vinculado a una dirección específica a través de uno de los métodos de enlace de su socket antes de que se puedan aceptar las conexiones. Además, el nuevo canal se crea invocando el método openServerSocketChannel del objeto SelectorProvider predeterminado en todo el sistema.

Al igual que el canal de socket, el canal de socket del servidor podría leer datos usando read()método Primero se asigna el búfer. Los datos leídos de un ServerSocketChannel se almacenan en el búfer. En segundo lugar, llamamos al método ServerSocketChannel.read () y lee los datos de un ServerSocketChannel en un búfer. El valor entero del método read () devuelve cuántos bytes se escribieron en el búfer

De manera similar, los datos se pueden escribir en el canal del socket del servidor usando write() método usando búfer como parámetro. Comúnmente usa el método de escritura en un ciclo while ya que es necesario repetir el método write () hasta que el búfer no tenga más bytes disponibles para escribir.

Métodos importantes de canal de socket

  • bind(SocketAddress local) - Este método se utiliza para vincular el canal de socket a la dirección local que se proporciona como parámetro para este método.

  • accept() - Este método se utiliza para aceptar una conexión realizada al conector de este canal.

  • connect(SocketAddress remote) - Este método se utiliza para conectar el enchufe a la dirección remota.

  • finishConnect() - Este método se utiliza para finalizar el proceso de conexión de un canal de enchufe.

  • getRemoteAddress() - Este método devuelve la dirección de la ubicación remota a la que está conectado el enchufe del canal.

  • isConnected() - Como ya se mencionó, este método devuelve el estado de conexión del canal del conector, es decir, si está conectado o no.

  • open() - El método abierto se utiliza para abrir un canal de socket para una dirección no especificada. Este método de conveniencia funciona como si se invocara el método open (), invocando el método de conexión en el canal de socket del servidor resultante, pasándolo de forma remota y luego devolviendo ese canal.

  • read(ByteBuffer dst) - Este método se utiliza para leer datos del búfer dado a través del canal de socket.

  • setOption(SocketOption<T> name, T value) - Este método establece el valor de una opción de socket.

  • socket() - Este método recupera un socket de servidor asociado con este canal.

  • validOps() - Este método devuelve un conjunto de operaciones que identifica las operaciones admitidas de este canal. Los canales de socket de servidor solo admiten la aceptación de nuevas conexiones, por lo que este método devuelve SelectionKey.OP_ACCEPT.

Ejemplo

El siguiente ejemplo muestra cómo enviar datos desde 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();
   }
}

Salida

La ejecución del cliente no imprimirá nada hasta que se inicie el servidor.

Servidor: 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();
   }
}

Salida

La ejecución del servidor imprimirá lo siguiente.

Connection Set:  /127.0.0.1:49558
File Received