Logo DIE

Sockets

Unidad de Apoyo para el Aprendizaje

Iniciar

Introducción


Hasta ahora todos los programas que se han realizado se encuentran en la misma computadora, pero ¿es posible realizar consultas a otros equipos? La respuesta es sí, para ello sólo se debe abrir un medio de comunicación entre los equipos que se deseen comunicar. Para crear el medio de comunicación se utilizan los sockets.

Un socket es un canal de comunicación entre dos dispositivos a través de la red. El proceso inicia cuando un dispositivo (cliente) busca conectarse con otro dispositivo (servidor) para consultar o solicitar información, por ejemplo. Para la comunicación en la red se debe establecer sobre un puerto en específico y, cuando la comunicación se haya establecido, los nodos (equipos) podrán intercambiar información a través de flujos de bytes.





Crear un canal de comunicación entre dos nodos en la red, un servidor y un cliente, para intercambiar información a través de flujos de bytes.

Sockets


En Java, la clase Socket se encuentra definida en el paquete java.net, la cual implementa una parte de la comunicación bidireccional entre un programa y otro. Estos sockets pueden comunicarse a través de la red de forma totalmente independiente de la plataforma donde se ejecute.

Además, java.net también posee la clase ServerSocket, que permite implementar un servidor para estar a la escucha de peticiones de conexiones por parte de los clientes.



Diagrama de bloques



El modelo de comunicaciones más básico entre sockets es el que envuelve a un servidor y a un cliente. El servidor espera la petición del cliente por un puerto específico. Cuando el cliente realice la petición, el servidor abrirá una conexión (flujo de datos).

El cliente realiza la petición al servidor por el puerto establecido y, de ser aceptada, se abre una conexión por la que ambos pueden intercambiar información mediante flujos de datos (InputStream y OutputStream).



Diagrama de bloques

Modelo de comunicación básico entre sockets



Rango de puertos IP

Existen una cantidad enorme de puertos disponibles (65,535) para cada dirección IP. Sin embargo, existen puertos que no se pueden utilizar porque están designados a servicios del sistema. A continuación, se presenta la clasificación de usos de puertos:

  • Puertos conocidos o reservados (0 al 1023): están reservados para procesos del sistema (demonios).

  • Puertos registrados (1024 al 49151): son de libre utilización y existen aplicaciones comerciales que los utilizan.

  • Puertos dinámicos o privados (49152 al 65535): son de tipo temporal y pueden usarse libremente.



Cliente en Java

La sintaxis para crear un socket cliente en Java es la siguiente:

Socket cliente;
        try {
                cliente = new Socket(“Servidor”, puerto);
        } catch (IOException ioe){
                System.out.println(e.getMessage());
}

La cadena “servidor” en el constructor de Socket se refiere al nombre o IP del equipo que va a estar a la espera de conexiones y el “puerto” al número por donde estará a la escucha.



Servidor en Java

Para crear un servidor con sockets es necesario crear un socket cliente y un socket servidor. La sintaxis es la siguiente:

Socket servicio;
        ServerSocket servidor;
        try {
                servidor = new ServerSocket(puerto);
                servicio = servidor.accept();
        } catch (IOException ioe){
                        System.out.println(e.getMessage());
        }

Cada vez que el servidor acepta una petición se crea un socket nuevo para que él pueda seguir a la escucha de otras solicitudes.



Flujos de entrada

DataInputStream permite crear flujos de entrada para recibir los datos que envíe un nodo.

La clase DataInputStream permite leer diferentes tipos de datos primitivos: read(), readChar(), readInt(), readDouble() y readLine().



Flujos de salida

Las clases PrintStream y DataOutputStream permiten crear flujos de salida para enviar información.

Ambas clases permiten escribir cualquier tipo de dato primitivo en forma de flujos de bytes.



Cerrar flujos y conexiones

Al final del programa es necesario cerrar todos los flujos de datos (tanto de entrada como de salida), así como los sockets creados.

Primero se deben cerrar los flujos de datos para que toda la información llegue a los nodos y, al final, se debe cerrar el canal de comunicación (el socket o los sockets).

Ejemplo

Este ejemplo consta de dos programas, el programa Server y el programa Client.

El programa Server crea un servidor que está a la escucha por la dirección IP de la máquina donde se ejecute por el puerto PORT (5432 en este caso). Este servidor acepta un máximo de cinco clientes.

Cuando ejecutes este programa debes hacerlo desde una terminal exclusiva para el Server; ya que el programa se va a quedar a la escucha de los clientes, los cuales deben conectarse desde otra terminal. Si cierras la terminal del servidor, ninguno de ellos podrá conectarse.

import java.io.OutputStream;
import java.io.DataOutputStream;
import java.io.DataInputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class Server {
        static final int PORT = 5432;

        public Server() {
                Socket service = null;
                DataOutputStream fds = null;
                DataInputStream dis = null;
                try {
                        ServerSocket server = new ServerSocket(PORT);
                         System.out.println("Escuchando por el puerto " + PORT);
                        for (int clients = 0 ; clients < 5; clients++) {
                                 service = server.accept();
                                System.out.println(“Conexión del cliente " + clients);
                                OutputStream writting = service.getOutputStream();
                                fds = new DataOutputStream(writting);
                                fds.writeUTF("Bienvenido cliente " + clients);
                                dis = new DataInputStream(service.getInputStream());
                                System.out.println(“Cliente " + clients + " dice: " + dis.readUTF());
                        }
                        System.out.println("Demasiados clientes por hoy.");
                } catch(Exception e) {
                        System.out.println(e.getMessage());
                        e.printStackTrace();
                } finally {
                        try {
                                if (fds != null) fds.close();
                                if (dis != null) dis.close();
                                if (service != null) service.close();
                      } catch (Exception e){
                                System.out.println(e.getMessage());
                      }
                }
             }
             public static void main(String [] arg) {
                      new Server();
             }
     }

El programa Client permite conectarse al servidor especificado, en este caso se conecta al servidor que está en la misma máquina (localhost) por el puerto 5432. Recibe un mensaje del servidor (InputStream) y envía un mensaje a éste (DataOutputStream).

import java.io.InputStream;
import java.io.DataOutputStream;
import java.io.DataInputStream;
import java.net.Socket;

public class Client {
        static final String SERVER = "localhost";
        static final int PORT = 5432;
        public Client( ) {
                Socket con = null;
                DataInputStream dis = null;
                DataOutputStream dos = null;
                try{
                        con = new Socket(SERVER, PORT);
                        InputStream read = con.getInputStream();
                        dis = new DataInputStream(read);
                        System.out.println(dis.readUTF());
                        dos = new
DataOutputStream(con.getOutputStream());
                        dos.writeUTF("Gracias por aceptarme.");
                } catch (Exception e) {
                        System.out.println(e.getMessage());
                } finally {
                        try {
                                if (dis != null) dis.close();
                                if (dos != null) dos.close();
                                if (con != null) con.close();
                        } catch (Exception e){
                                System.out.println(e.getMessage());
                        }
                 }
             }
        public static void main(String [] arg) {
                new Client();
             }
}





ícono

Actividad. Flujos de comunicación entre dos equipos

Un socket es un canal de comunicación entre dos equipos en la red. A través de éste los equipos se pueden enviar mensajes y compartir información.

Los sockets son la base de comunicación de cualquier servicio que se ofrezca en Internet: http, ftp, ssh, entre otros. Es lo que se conoce como arquitectura cliente-servidor.

Te recomendamos realizar esta actividad en una computadora de escritorio para mejor visualización de los ejercicios y las retroalimentaciones.

ícono

Autoevaluación. Canales de comunicación en Java

Un canal de comunicación en la red permite comunicar dos o más equipos de cómputo a través de la red de datos. Para poder hacer este canal de comunicación en Java se pueden crear Sockets. Para poder crear Sockets en Java es necesario conocer las clases que permiten llevar a cabo la comunicación, así como la manera en la que se transmite la información a través del canal.


Fuentes de información

Dean, J. y Dean, R. (2009). Introducción a la programación con Java. McGraw-Hill.

Martín, A. (2008). Programador certificado Java 2 (2.a ed.). Alfaomega Grupo Editor.

Sierra, K. y Bates, B. (2008). SCJP Sun Certified Programmer for Java 6 Study Guide. McGraw-Hill.


Cómo citar


Solano, J. A. (2020). Sockets. Unidades de Apoyo para el Aprendizaje. CUAIEED/Facultad de Ingeniería-UNAM. (Vínculo)