No es un bug, es una característica no documentada

miércoles, 20 de enero de 2016

Procesos y servicios. Programación de Sockets (I)

¿Qué son los sockets?

Los protocolos TCP y UDP utilizan la abstracción de sockets para proporcionar los puntos extremos de la comunicación entre aplicaciones o procesos.

Para los procesos receptores de mensajes, su conector debe tener asociado dos campos:
  • La dirección IP del host en el que la aplicación está corriendo.
  • El puerto local a través del cual la aplicación se comunica y que identifica el proceso.




Funcionamient en general de un socket 


El programa cliente conoce el nombre de la máquina en la que se ejecuta el servidor y el número de puerto por el que escucha las peticiones. Para realizar una solicitud de conexión, el cliente realiza la petición a la máquina a través del puerto.


Si todo va bien, el servidor acepta la conexión. Una vez aceptada, el servidor obtiene un nuevo socket sobre un puerto diferente. Esto se debe a que por un lado debe seguir atendiendo las peticiones de conexión mediante el socket original y por otro debe antender las necesidades del cliente que se conectó.


En el lado del cliente, si se acepta la conexión, se crea un socket y el cliente puede utilizarlo para comunicarse con el servidor. Este socket utiliza un número de puerto diferente al usado para conectarse al servidor. El cliente y el servidor pueden ahora comunicarse escribiendo y leyendo por sus respectivos sockets.

Clase ServerSocket

Se utiliza para implementar el extremo de la conexión que corresponde al servidor, donde se crea un conector en el puerto del servidor que escucha las peticiones de conexión de los clientes.

Constructores


Algunos métodos importantes


Ejemplo

Archivo SocketServidor.java

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

public class SocketServidor {

      public static void main(String[] args) throws IOException {
           
            int Puerto = 6000;// Puerto
            ServerSocket Servidor=null;
           
            Servidor = new ServerSocket(Puerto);
                       
            System.out.println("Escuchando en " + Servidor.getLocalPort());
           
            Socket clientel = Servidor.accept();//esperando a un cliente
            //realizar acciones con clientel
           
            Socket cliente2 = Servidor.accept();//esperando a otro cliente
            //realizar acciones con cliente2
           
            Servidor.close(); //cierro socket servidor
           
      }//fin de main

}//fin de SocketServidor

Clase Socket

Implementa un extremo de la conexión TCP.

Constructores


Algunos métodos importantes


Ejemplo

Archivo SocketCliente.java

import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;

public class SocketCliente {

      public static void main(String[] args) throws IOException {
           
            String Host = "localhost";
            int Puerto = 6000;//puerto remoto
           
            // ABRIR SOCKET
            Socket Cliente = new Socket(Host, Puerto);//conecta
           
            InetAddress i= Cliente.getInetAddress ();
            System.out.println("Puerto local: "+ Cliente.getLocalPort());
            System.out.println("Puerto Remoto: "+ Cliente.getPort()); 
            System.out.println("Host Remoto: "+ i.getHostName().toString()); 
            System.out.println("IP Host Remoto: "+ i.getHostAddress().toString());
           
            Cliente.close();// Cierra el socket
               
      }//fin de main
     
}//fin de SocketCliente

Gestión de Sockets TCP

El programa servidor crea un socket de servidor definiendo un puerto, mediante el método ServerSocket(port), y espera mediante el método accept() a que el cliente solicite la conexión.

Cuando el cliente solicita una conexión, el servidor abrirá la conexión al socket con el método accept().

El cliente establece una conexión con la máquina host a través del uerto especificado mediante el método Socket(host, port).


El cliente y el servidor se comunican con manejadores InputStream y OutputStream. El cliente escribe los mensajes en el OutputStream asociado al socket y el servidor leerá los mensajes del cliente de InputStream. Igualmente el servidor escribirá los mensajes al OutputStream y el cliente los leerá del InputStream.


Hay puertos TCP de 0 a 65535.

Los puertos en el rango de 0 a 1023 están reservados para servicios privilegiados.

De 1024 a 49151 están reservados para aplicaciones concretas (por ejemplo el 3306 lo usa MySQL, el 1521 Oracle).

De 49152 a 65535 no están reservados para ninguna aplicación concreta.

Ejemplo.

El programa servidor (Ejemplo1Servidor) recibe un mensaje de un cliente y lo muestra por pantalla; después envía un mensaje al cliente. Se han eliminado los bloques try-catch para que el código resulte más legible.

Archivo Ejemplo1Servidor.java

import java.io.*;
import java.net.*;

public class Ejemplo1Servidor {
     
      public static void main(String[] argthrows IOException {
           
            int numeroPuerto = 6000;// Puerto
            ServerSocket servidor = new ServerSocket(numeroPuerto);
            Socket clienteConectado = null;
            System.out.println("Esperando al cliente.....");
            clienteConectado = servidor.accept();
           
            // CREO FLUJO DE ENTRADA DEL CLIENTE   
            InputStream entrada = null;
            entrada = clienteConectado.getInputStream();
            DataInputStream flujoEntrada = new DataInputStream(entrada);
           
            // EL CLIENTE ME ENVIA UN MENSAJE
            System.out.println("Recibiendo del CLIENTE: \n\t" + flujoEntrada.readUTF());
           
            // CREO FLUJO DE SALIDA AL CLIENTE
            OutputStream salida = null;
            salida = clienteConectado.getOutputStream();
            DataOutputStream flujoSalida = new DataOutputStream(salida);
           
            // ENVIO UN SALUDO AL CLIENTE
            flujoSalida.writeUTF("Saludos al cliente del servidor");
           
            // CERRAR STREAMS Y SOCKETS
            entrada.close();
            flujoEntrada.close();
            salida.close();
            flujoSalida.close();
            clienteConectado.close();
            servidor.close();
           
      }// main
     
}// fin de Ejemplo1Servidor
El programa cliente (Ejemplo1Cliente) envía un mensaje al servidor y después recibe un mensaje del servidor visualizándolo en pantalla, se ha simplificado la obtención de los flujos de entrada y salida.

Archivo Ejemplo1Cliente.java

import java.io.*;
import java.net.*;

public class Ejemplo1Cliente {
     
      public static void main(String[] argsthrows Exception {
           
            String Host = "localhost";
            int Puerto = 6000;//puerto remoto
           
            System.out.println("PROGRAMA CLIENTE INICIADO....");
            Socket Cliente = new Socket(HostPuerto);
           
            // CREO FLUJO DE SALIDA AL SERVIDOR
            DataOutputStream flujoSalida = new DataOutputStream(Cliente.getOutputStream());
           
            // ENVIO UN SALUDO AL SERVIDOR
            flujoSalida.writeUTF("SaludOS al SERVIDOR DESDE EL CLIENTE");
           
            // CREO FLUJO DE ENTRADA AL SERVIDOR
            DataInputStream flujoEntrada = new DataInputStream(Cliente.getInputStream());
           
            // EL SERVIDOR ME ENVIA UN MENSAJE   
            System.out.println("Recibiendo del SERVIDOR: \n\t" + flujoEntrada.readUTF());
           
            // CERRAR STREAMS Y SOCKETS
            flujoEntrada.close();
            flujoSalida.close();
            Cliente.close();
           
      }// fin de main
     

}// Fin de Ejemplo1Cliente

1 comentario:

  1. De mucho interés, agradezco vuestra valiosa aportación a la comunidad en esta jornada.

    ResponderEliminar