Java NIO: canal de socket

El canal de socket Java NIO es un canal de tipo seleccionable, lo que significa que se puede multiplexar usando el selector, utilizado para los enchufes de conexión de flujo de datos orientados al flujo. El canal de socket se puede crear invocando su estática open() método, siempre que no exista ningún enchufe preexistente. El canal de enchufe se crea invocando el método abierto pero aún no está conectado. connect() Un punto que se debe mencionar aquí es que si el canal no está conectado y se intenta realizar cualquier operación de E / S, entonces este canal lanza NotYetConnectedException. Por lo tanto, uno debe asegurarse de que el canal esté conectado antes de realizar cualquier E / S. Una vez que el canal se conecta, permanece conectado hasta que se cierra. El estado del canal del zócalo se puede determinar invocando su isConnected método.

La conexión del canal de socket se puede finalizar invocando su finishConnect() Se puede determinar si una operación de conexión está en progreso invocando el método isConnectionPending. Por defecto, el canal de socket admite conexión sin bloqueo. También admite apagado asincrónico, que es similar a la operación de cierre asincrónico especificada en la clase Channel.

Los canales de socket son seguros para su uso por varios subprocesos simultáneos. Admiten lectura y escritura simultáneas, aunque como máximo un hilo puede estar leyendo y como máximo un hilo puede estar escribiendo en un momento dado. Los métodos connect y finishConnect se sincronizan mutuamente entre sí, y un intento de iniciar una operación de lectura o escritura mientras una invocación de uno de estos métodos está en curso se bloqueará hasta que se complete la invocación.

Métodos importantes de canal de enchufe

  • 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.

  • 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() and open((SocketAddress remote) - El método abierto se usa para abrir un canal de socket para una dirección no especificada mientras que el método abierto parametriza abre el canal para una dirección remota especificada y también se conecta a él.Este método de conveniencia funciona como si se invocara el método open (), invocando el método de conexión en el resultado socket, 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.

  • isConnectionPending() - Este método indica si hay una operación de conexión en curso en este canal.

Ejemplo

El siguiente ejemplo muestra cómo enviar datos desde Java NIO SocketChannel.

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