Java - Redes

El término programación de red se refiere a la escritura de programas que se ejecutan en varios dispositivos (computadoras), en los que todos los dispositivos están conectados entre sí mediante una red.

El paquete java.net de las API de J2SE contiene una colección de clases e interfaces que proporcionan detalles de comunicación de bajo nivel, lo que le permite escribir programas que se centren en resolver el problema en cuestión.

El paquete java.net proporciona soporte para los dos protocolos de red comunes:

  • TCP- TCP significa Protocolo de control de transmisión, que permite una comunicación confiable entre dos aplicaciones. TCP se utiliza normalmente a través del Protocolo de Internet, que se conoce como TCP / IP.

  • UDP - UDP son las siglas de User Datagram Protocol, un protocolo sin conexión que permite la transmisión de paquetes de datos entre aplicaciones.

Este capítulo proporciona una buena comprensión de los dos temas siguientes:

  • Socket Programming - Este es el concepto más utilizado en Networking y se ha explicado con mucho detalle.

  • URL Processing- Esto se cubriría por separado. Haga clic aquí para obtener información sobre el procesamiento de URL en lenguaje Java.

Programación de socket

Los sockets proporcionan el mecanismo de comunicación entre dos computadoras que utilizan TCP. Un programa cliente crea un conector en su extremo de la comunicación e intenta conectar ese conector a un servidor.

Cuando se realiza la conexión, el servidor crea un objeto de socket en su extremo de la comunicación. El cliente y el servidor ahora pueden comunicarse escribiendo y leyendo desde el socket.

La clase java.net.Socket representa un socket y la clase java.net.ServerSocket proporciona un mecanismo para que el programa servidor escuche a los clientes y establezca conexiones con ellos.

Los siguientes pasos ocurren cuando se establece una conexión TCP entre dos computadoras usando sockets:

  • El servidor crea una instancia de un objeto ServerSocket, que indica en qué número de puerto se producirá la comunicación.

  • El servidor invoca el método accept () de la clase ServerSocket. Este método espera hasta que un cliente se conecta al servidor en el puerto dado.

  • Una vez que el servidor está esperando, un cliente crea una instancia de un objeto Socket, especificando el nombre del servidor y el número de puerto al que conectarse.

  • El constructor de la clase Socket intenta conectar el cliente al servidor especificado y al número de puerto. Si se establece la comunicación, el cliente ahora tiene un objeto Socket capaz de comunicarse con el servidor.

  • En el lado del servidor, el método accept () devuelve una referencia a un nuevo socket en el servidor que está conectado al socket del cliente.

Una vez establecidas las conexiones, la comunicación puede producirse mediante flujos de E / S. Cada conector tiene un OutputStream y un InputStream. El OutputStream del cliente está conectado al InputStream del servidor y el InputStream del cliente está conectado al OutputStream del servidor.

TCP es un protocolo de comunicación bidireccional, por lo que los datos se pueden enviar a través de ambos flujos al mismo tiempo. A continuación se muestran las clases útiles que proporcionan un conjunto completo de métodos para implementar sockets.

Métodos de clase ServerSocket

los java.net.ServerSocket Las aplicaciones del servidor utilizan la clase para obtener un puerto y escuchar las solicitudes de los clientes.

La clase ServerSocket tiene cuatro constructores:

No Señor. Método y descripción
1

public ServerSocket(int port) throws IOException

Intenta crear un socket de servidor vinculado al puerto especificado. Se produce una excepción si el puerto ya está vinculado por otra aplicación.

2

public ServerSocket(int port, int backlog) throws IOException

Al igual que en el constructor anterior, el parámetro backlog especifica cuántos clientes entrantes almacenar en una cola de espera.

3

public ServerSocket(int port, int backlog, InetAddress address) throws IOException

Al igual que en el constructor anterior, el parámetro InetAddress especifica la dirección IP local a la que enlazar. InetAddress se utiliza para servidores que pueden tener varias direcciones IP, lo que permite al servidor especificar en cuál de sus direcciones IP aceptar las solicitudes de los clientes.

4

public ServerSocket() throws IOException

Crea un socket de servidor independiente. Cuando use este constructor, use el método bind () cuando esté listo para vincular el socket del servidor.

Si el constructor ServerSocket no lanza una excepción, significa que su aplicación se ha enlazado con éxito al puerto especificado y está lista para las solicitudes del cliente.

A continuación se muestran algunos de los métodos comunes de la clase ServerSocket:

No Señor. Método y descripción
1

public int getLocalPort()

Devuelve el puerto en el que escucha el socket del servidor. Este método es útil si pasó 0 como número de puerto en un constructor y dejó que el servidor encuentre un puerto por usted.

2

public Socket accept() throws IOException

Espera un cliente entrante. Este método se bloquea hasta que un cliente se conecta al servidor en el puerto especificado o el socket se agota, asumiendo que el valor de tiempo de espera se ha establecido usando el método setSoTimeout (). De lo contrario, este método se bloquea indefinidamente.

3

public void setSoTimeout(int timeout)

Establece el valor de tiempo de espera para el tiempo que el socket del servidor espera a un cliente durante el accept ().

4

public void bind(SocketAddress host, int backlog)

Vincula el socket al servidor y al puerto especificados en el objeto SocketAddress. Utilice este método si ha creado una instancia de ServerSocket utilizando el constructor sin argumentos.

Cuando ServerSocket invoca accept (), el método no regresa hasta que un cliente se conecta. Después de que un cliente se conecta, ServerSocket crea un nuevo Socket en un puerto no especificado y devuelve una referencia a este nuevo Socket. Ahora existe una conexión TCP entre el cliente y el servidor y puede comenzar la comunicación.

Métodos de clase de socket

los java.net.SocketLa clase representa el socket que tanto el cliente como el servidor utilizan para comunicarse entre sí. El cliente obtiene un objeto Socket creando una instancia de uno, mientras que el servidor obtiene un objeto Socket del valor de retorno del método accept ().

La clase Socket tiene cinco constructores que un cliente usa para conectarse a un servidor:

No Señor. Método y descripción
1

public Socket(String host, int port) throws UnknownHostException, IOException.

Este método intenta conectarse al servidor especificado en el puerto especificado. Si este constructor no lanza una excepción, la conexión es exitosa y el cliente está conectado al servidor.

2

public Socket(InetAddress host, int port) throws IOException

Este método es idéntico al constructor anterior, excepto que el host se indica mediante un objeto InetAddress.

3

public Socket(String host, int port, InetAddress localAddress, int localPort) throws IOException.

Se conecta al host y al puerto especificados, creando un socket en el host local en la dirección y el puerto especificados.

4

public Socket(InetAddress host, int port, InetAddress localAddress, int localPort) throws IOException.

Este método es idéntico al constructor anterior, excepto que el host se indica mediante un objeto InetAddress en lugar de un String.

5

public Socket()

Crea un enchufe sin conectar. Utilice el método connect () para conectar este enchufe a un servidor.

Cuando el constructor de Socket regresa, no simplemente crea una instancia de un objeto Socket, sino que en realidad intenta conectarse al servidor y puerto especificados.

Aquí se enumeran algunos métodos de interés en la clase Socket. Tenga en cuenta que tanto el cliente como el servidor tienen un objeto Socket, por lo que estos métodos pueden ser invocados tanto por el cliente como por el servidor.

No Señor. Método y descripción
1

public void connect(SocketAddress host, int timeout) throws IOException

Este método conecta el socket al host especificado. Este método es necesario solo cuando crea una instancia de Socket utilizando el constructor sin argumentos.

2

public InetAddress getInetAddress()

Este método devuelve la dirección de la otra computadora a la que está conectado este enchufe.

3

public int getPort()

Devuelve el puerto al que está vinculado el socket en la máquina remota.

4

public int getLocalPort()

Devuelve el puerto al que está vinculado el socket en la máquina local.

5

public SocketAddress getRemoteSocketAddress()

Devuelve la dirección del enchufe remoto.

6

public InputStream getInputStream() throws IOException

Devuelve el flujo de entrada del socket. El flujo de entrada está conectado al flujo de salida del enchufe remoto.

7

public OutputStream getOutputStream() throws IOException

Devuelve el flujo de salida del socket. El flujo de salida está conectado al flujo de entrada del enchufe remoto.

8

public void close() throws IOException

Cierra el socket, lo que hace que este objeto Socket ya no pueda conectarse nuevamente a ningún servidor.

Métodos de clase InetAddress

Esta clase representa una dirección de Protocolo de Internet (IP). Aquí están los siguientes métodos útiles que necesitaría mientras realiza la programación de sockets:

No Señor. Método y descripción
1

static InetAddress getByAddress(byte[] addr)

Devuelve un objeto InetAddress dada la dirección IP sin formato.

2

static InetAddress getByAddress(String host, byte[] addr)

Crea una InetAddress basada en el nombre de host y la dirección IP proporcionados.

3

static InetAddress getByName(String host)

Determina la dirección IP de un host, dado el nombre del host.

4

String getHostAddress()

Devuelve la cadena de dirección IP en una presentación textual.

5

String getHostName()

Obtiene el nombre de host para esta dirección IP.

6

static InetAddress InetAddress getLocalHost()

Devuelve el host local.

7

String toString()

Convierte esta dirección IP en una cadena.

Ejemplo de cliente de socket

El siguiente GreetingClient es un programa cliente que se conecta a un servidor mediante un socket y envía un saludo, y luego espera una respuesta.

Ejemplo

// File Name GreetingClient.java
import java.net.*;
import java.io.*;

public class GreetingClient {

   public static void main(String [] args) {
      String serverName = args[0];
      int port = Integer.parseInt(args[1]);
      try {
         System.out.println("Connecting to " + serverName + " on port " + port);
         Socket client = new Socket(serverName, port);
         
         System.out.println("Just connected to " + client.getRemoteSocketAddress());
         OutputStream outToServer = client.getOutputStream();
         DataOutputStream out = new DataOutputStream(outToServer);
         
         out.writeUTF("Hello from " + client.getLocalSocketAddress());
         InputStream inFromServer = client.getInputStream();
         DataInputStream in = new DataInputStream(inFromServer);
         
         System.out.println("Server says " + in.readUTF());
         client.close();
      } catch (IOException e) {
         e.printStackTrace();
      }
   }
}

Ejemplo de servidor de socket

El siguiente programa GreetingServer es un ejemplo de una aplicación de servidor que usa la clase Socket para escuchar a los clientes en un número de puerto especificado por un argumento de línea de comandos:

Ejemplo

// File Name GreetingServer.java
import java.net.*;
import java.io.*;

public class GreetingServer extends Thread {
   private ServerSocket serverSocket;
   
   public GreetingServer(int port) throws IOException {
      serverSocket = new ServerSocket(port);
      serverSocket.setSoTimeout(10000);
   }

   public void run() {
      while(true) {
         try {
            System.out.println("Waiting for client on port " + 
               serverSocket.getLocalPort() + "...");
            Socket server = serverSocket.accept();
            
            System.out.println("Just connected to " + server.getRemoteSocketAddress());
            DataInputStream in = new DataInputStream(server.getInputStream());
            
            System.out.println(in.readUTF());
            DataOutputStream out = new DataOutputStream(server.getOutputStream());
            out.writeUTF("Thank you for connecting to " + server.getLocalSocketAddress()
               + "\nGoodbye!");
            server.close();
            
         } catch (SocketTimeoutException s) {
            System.out.println("Socket timed out!");
            break;
         } catch (IOException e) {
            e.printStackTrace();
            break;
         }
      }
   }
   
   public static void main(String [] args) {
      int port = Integer.parseInt(args[0]);
      try {
         Thread t = new GreetingServer(port);
         t.start();
      } catch (IOException e) {
         e.printStackTrace();
      }
   }
}

Compile el cliente y el servidor y luego inicie el servidor de la siguiente manera:

$ java GreetingServer 6066
Waiting for client on port 6066...

Verifique el programa del cliente de la siguiente manera:

Salida

$ java GreetingClient localhost 6066
Connecting to localhost on port 6066
Just connected to localhost/127.0.0.1:6066
Server says Thank you for connecting to /127.0.0.1:6066
Goodbye!