jueves, 30 de agosto de 2012

Comunicaciones en red

Java permite realizar aplicaciones que posean comunicación en red, mediante el uso del modelo cliente servidor.

Modelo Cliente Servidor

El modelo cliente servidor permite la comunicación entre un equipo denominado servidor y un conjunto de equipos denominados clientes. Los clientes se encuentran en constante comunicación con el servidor y a través de este, pueden establecer comunicación con otros clientes. El servidor es el encargado de aceptar solicitudes de conexión por parte de los clientes y los clientes deben conectarse al servidor a través de su dirección lógica y de su puerto de aplicación. Esto significa que todas las gestiones que se realizan se concentran en el servidor, de manera que en él se disponen los diferentes requerimientos del sistema.

Socket Y ServerSocket

El socket es el elemento que permite establecer una comunicación entre un servidor y múltiples clientes. Es posible trabajar comunicaciones mediante la clase Socket del paquete java.net. Esta clase permite crear conexiones que utiliza el protocolo TCP, entre dos computadores. Los Sockets con conectores entre dos computadores remotos en donde su comunicación es continua y finaliza cuando uno de los dos computadores cierra su conexión. La clase ServerSocket es una clase que pertenece al paquete java.net que sirve para atender peticiones de conexiones, lo cual es necesario para la creación de un servidor. Para crear un servidor, se debe crear un Socket y un ServerSocket. El ServerSocket debe tener como parámetro el número de puerto de la aplicación. Este número de puerto debe ser un número superior a 1024, con el fin de que la aplicación no presente conflicto con otras aplicaciones o protocolos de redes de computadores. La clase ServerSocket tiene el método accept el cual permite aceptar una conexión. Esto indica que el servidor debe tener un proceso iterativo que tenga un proceso para aceptar conexiones. El método accept retorna un Socket que contiene la información del cliente remoto que se ha conectado. La clase Socket, posee los métodos getInputStream que retorna un Stream con el cual el servidor puede recibir información por parte del cliente conectado y getOutputStream que retorna un Stream con el cual el servidor puede enviar información al cliente conectado. La implementación para crear un servidor con una sola conexión por parte de un cliente es la siguiente.

01try {
02ServerSocket serverSocket = new ServerSocket(5000);
03System.out.println("Esperando nueva conexion");
04Socket socket = serverSocket.accept();
05System.out.println("Conexion desde: "+socket.getInetAddress().getHostName()+" IP: " + this.socket.getInetAddress().getHostAddress());
06ObjectInputStream input = new ObjectInputStream(socket.getInputStream());
07ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream());
08} catch (IOException e) {
09 e.printStackTrace();
10}catch (ClassNotFoundException e) {
11 e.printStackTrace();
12

En esta implementación de servidor, se obtiene un Socket al presentarse una conexión. La clase Socket además provee el método getInetAddress, el cual retorna un object instancia de la clase InetAddress que a su vez cuenta con los métodos getHostName y getHostAddress que permiten capturar el nombre y dirección IP respectivamente del cliente conectado. El cliente, puede conectarse al servidor, una vez que éste se encuentre esperando conexión. Entonces en el cliente debe crearse un Socket al cual se le envía por parámetro una dirección IP a través de la clase InetAddress y el número del puerto de servidor.

1try {
2Socket socket = new Socket(InetAddress.getByName(127.0.0.1),5000);
3ObjectInputStream input = new ObjectInputStream(socket.getInputStream());
4ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream());
5} catch (IOException e) {
6 e.printStackTrace();
7}catch (ClassNotFoundException e) {
8 e.printStackTrace();
9}  

De la misma forma que en el servidor, se puede obtener un Stream para enviar datos y otro para recibir datos. El modelo cliente servidor, indica que se puede conectar un servidor con múltiples clientes. Para ello, es necesario modificar la implementación anterior con el fin de permitir múltiples conexiones. La implementación para crear un servidor con múltiples conexiones por parte de clientes es la siguiente.

01try {
02 ServerSocket serverSocket = new ServerSocket(5000);
03 int contador=1;
04 while(true){
05  System.out.println("Esperando nueva conexion");
06  Socket socket = serverSocket.accept();
07  System.out.println( "Conexion " + contador +" desde: " + this.socket.getInetAddress().getHostName()+" IP: "+ this.socket.getInetAddress().getHostAddress());
08  contador++;   
09  ObjectInputStream input = new ObjectInputStream(socket.getInputStream());
10  ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream());
11 }
12} catch (IOException e) {
13 e.printStackTrace();
14}catch (ClassNotFoundException e) {
15 e.printStackTrace();
16}  

Esta implementación atiende las conexiones de clientes mediante un proceso iterativo sin fin. Sin embargo, en el momento de recibir una conexión, crea los Stream de entrada y salida, pero ejecuta la siguiente iteración y queda de nuevo esperando conexión. Esto indica que este servidor estará en capacidad únicamente de aceptar conexiones pero no podrá enviar ni recibir mensajes. Para agregar funcionalidad de envió y recepción de mensajes, es necesario implementar un hilo, para que el servidor cree una instancia del hilo por cada conexión. Entonces, a través de cada hilo, el servidor puede enviar y recibir información. La implementación del hilo es la siguiente.

01package Servidor;
02 
03import java.io.IOException;
04import java.io.ObjectInputStream;
05import java.io.ObjectOutputStream;
06 
07public class HiloServidor extends Thread {
08 private ObjectOutputStream output;
09 private ObjectInputStream input;
10 private Servidor servidor;
11 boolean activo=true;
12 private String mensajeRecibido;
13  
14 public HiloServidor(String nombre, ObjectInputStream input, ObjectOutputStream output, Servidor servidor){
15  super(nombre);
16  this.input=input;
17  this.output=output;
18  this.servidor=servidor;
19 }
20  
21 public void run(){
22  while(this.activo){
23   try {
24    this.mensajeRecibido = (String)this.input.readObject();
25    System.out.println(this.getName()+" dice: "+this.mensajeRecibido);
26    this.servidor.enviarMensaje(this.mensajeRecibido);
27   } catch (IOException e) {
28    this.activo=false;
29   } catch (ClassNotFoundException e) {
30    e.printStackTrace();
31   }
32  }
33 }
34  
35 public void enviar (String mensaje){
36  try {
37   this.output.writeObject(mensaje);
38   this.output.flush();
39  } catch (IOException e) {
40   e.printStackTrace();
41  }
42 }
43}

Este hilo recibe a través del constructor, un nombre del hilo, un Stream de entrada, un Stream de salida y una referencia al servidor. Esta última se crea con el objetivo de tener acceso a los servicios implementados en el servidor. El método run se encarga de recibir información a través del Stream de entrada, por medio del método readObject, al cual se le debe aplicar un casting. El método enviar se encarga de enviar información a través del Stream de salida, por medio de los métodos writeObject y flush. Para que el servidor pueda hacer uso del hilo, debe modificarse de tal forma que por cada conexión pueda crear un hilo y almacenarlo. Al crear un hilo, el servidor debe enviar el nombre del hilo, el Stream de entrada, el Stream de salida y el servidor a través de la sentencia this. La implementación del nuevo servidor es la siguiente.

01package Servidor;
02 
03import java.io.IOException;
04import java.io.ObjectInputStream;
05import java.io.ObjectOutputStream;
06import java.net.ServerSocket;
07import java.net.Socket;
08import java.util.Iterator;
09import java.util.Vector;
10 
11public class Servidor {
12 private Socket socket;
13 private ServerSocket serverSocket;
14 private Vector hilosServidor = new Vector();
15 
16 public void iniciarServidor(){
17  try {
18   this.serverSocket = new ServerSocket(5000);
19   int contador=1;
20   while(true){
21    System.out.println("Esperando nueva conexion");
22    this.socket = serverSocket.accept();
23       System.out.println("Conexion " + contador +" desde: " + this.socket.getInetAddress().getHostName()+" IP: "+ this.socket.getInetAddress().getHostAddress());
24    contador++;   
25    ObjectInputStream input = new ObjectInputStream(this.socket.getInputStream());
26    ObjectOutputStream output = new ObjectOutputStream(this.socket.getOutputStream());
27    HiloServidor hiloServidor = new HiloServidor("Cliente "+contador, input, output, this);
28    hiloServidor.start();
29    this.hilosServidor.add(hiloServidor);
30   }
31  } catch (IOException e) {
32   e.printStackTrace();
33  }catch (ClassNotFoundException e) {
34   e.printStackTrace();
35  }  
36 }
37  
38 public void enviarMensaje(String mensaje){
39  Iterator iterator = this.hilosServidor.iterator();
40  while(iterator.hasNext()){
41   HiloServidor hiloTemp=(HiloServidor)iterator.next();
42   hiloTemp.enviar(hiloTemp.getName()+" dice: "+mensaje);  
43  }
44 }
45 
46 public static void main(String[] args) {
47  Servidor servidor = new Servidor();
48  servidor.iniciarServidor();
49 }
50}

El método iniciarServidor, se encarga de recibir conexiones. Por cada conexión recibida crea un hilo que adiciona en un vector. Cada hilo creado, envía por el constructor el nombre, el Stream de entrada, el Stream de salida y una referencia al servidor. El método enviarMensaje, envía un mensaje que recibe por parámetro a todos los clientes, mediante un proceso iterativo de los hilos almacenados en el vector. En la aplicación del cliente, también se requiere crear un hilo que se encarga de recibir mensajes por parte del servidor. La implementación es la siguiente.

01package Cliente;
02 
03import java.io.IOException;
04import java.io.ObjectInputStream;
05 
06public class HiloCliente extends Thread {
07 private ObjectInputStream input;
08 private boolean activo=true;
09 
10 public HiloCliente(ObjectInputStream input) {
11  this.input=input; 
12 }
13  
14 public void run(){
15  while(this.activo){
16   String mensaje;
17   try {
18    mensaje = (String)this.input.readObject();
19    System.out.println(mensaje);     
20   } catch (IOException e) {
21    this.activo=false;
22   } catch (ClassNotFoundException e) {
23    e.printStackTrace();
24   }
25  }
26 }
27}

El método run de forma permanente intenta leer un mensaje por parte del servidor. En caso que ocurra una excepción, el atributo activo pasa a falso y el hilo deja de leer a través del Stream de entrada que fue recibido por el constructor.

Chat

Una de las aplicaciones clásicas del modelo cliente servidor mediante Sockets es el chat. Un chat debe tener un servidor que reciba conexiones de múltiples clientes. Cuando un cliente se conecta, el servidor notifica a todos los clientes que este nuevo cliente se ha conectado. Cuando un cliente envía un mensaje, el servidor reenvía este mensaje a todos los clientes. La implementación del chat es la siguiente.

Clase Servidor
01package Servidor;
02 
03import java.io.IOException;
04import java.io.ObjectInputStream;
05import java.io.ObjectOutputStream;
06import java.net.ServerSocket;
07import java.net.Socket;
08import java.util.Iterator;
09import java.util.Vector;
10 
11public class Servidor {
12 private Socket socket;
13 private ServerSocket serverSocket;
14 private String nombreUsuarioConectado;
15 private Vector hilosServidor = new Vector();
16 
17 public void iniciarServidor(){
18  try {
19   this.serverSocket = new ServerSocket(5000);
20   int contador=1;
21   while(true){
22    System.out.println("Esperando nueva conexion");
23    this.socket = serverSocket.accept();
24       System.out.println( "Conexion " + contador +" desde: " + this.socket.getInetAddress().getHostName()+" IP: "+ this.socket.getInetAddress().getHostAddress());
25    contador++;   
26    ObjectInputStream input = new ObjectInputStream(this.socket.getInputStream());
27    ObjectOutputStream output = new ObjectOutputStream(this.socket.getOutputStream());
28    this.nombreUsuarioConectado = (String)input.readObject();
29    System.out.println(this.nombreUsuarioConectado+" se ha conectado");
30    HiloServidor hiloServidor = new HiloServidor(this.nombreUsuarioConectado, input, output, this);
31    hiloServidor.start();
32    this.hilosServidor.add(hiloServidor);
33    this.enviarClienteConectado();
34   }
35  } catch (IOException e) {
36   e.printStackTrace();
37  }catch (ClassNotFoundException e) {
38   e.printStackTrace();
39  }  
40 }
41  
42 public void enviarClienteConectado(){
43  Iterator iterator = this.hilosServidor.iterator();
44  while(iterator.hasNext()){
45   HiloServidor hiloTemp=(HiloServidor)iterator.next();
46   hiloTemp.enviar(this.nombreUsuarioConectado+" se ha conectado");  
47  }
48 }
49  
50 public void enviarMensaje(String mensaje){
51  Iterator iterator = this.hilosServidor.iterator();
52  while(iterator.hasNext()){
53   HiloServidor hiloTemp=(HiloServidor)iterator.next();
54   hiloTemp.enviar(hiloTemp.getName()+" dice: "+mensaje);  
55  }
56 }
57 
58 public static void main(String[] args) {
59  Servidor servidor = new Servidor();
60  servidor.iniciarServidor();
61 }
62}

En la clase Servidor, el método iniciarServidor se encarga de recibir conexiones por parte de clientes. Una vez hecha la conexión recibe un nombre de cliente, el cual será el identificador del hilo. El método enviarClienteConectado, se encarga de enviar a todos los clientes una notificación de conexión de un nuevo cliente. El método enviarMensaje, se encarga de enviar el mensaje que recibe por parámetro a todos los clientes conectados.

Clase HiloServidor
01package Servidor;
02 
03import java.io.IOException;
04import java.io.ObjectInputStream;
05import java.io.ObjectOutputStream;
06 
07public class HiloServidor extends Thread {
08 private ObjectOutputStream output;
09 private ObjectInputStream input;
10 private Servidor servidor;
11 boolean activo=true;
12 private String mensajeRecibido;
13  
14 public HiloServidor(String nombre, ObjectInputStream input, ObjectOutputStream output, Servidor servidor){
15  super(nombre);
16  this.input=input;
17  this.output=output;
18  this.servidor=servidor;
19 }
20  
21 public void run(){
22  while(this.activo){
23   try {
24    this.mensajeRecibido = (String)this.input.readObject();
25    System.out.println(this.getName()+" dice: "+this.mensajeRecibido);
26    this.servidor.enviarMensaje(this.mensajeRecibido);
27   } catch (IOException e) {
28    this.activo=false;
29   } catch (ClassNotFoundException e) {
30    e.printStackTrace();
31   }
32  }
33 }
34  
35 public void enviar (String mensaje){
36  try {
37   this.output.writeObject(mensaje);
38   this.output.flush();
39  } catch (IOException e) {
40   e.printStackTrace();
41  }
42 }
43}

En la clase HiloServidor, el método run se encarga de recibir mensajes del cliente asociado con el hilo. Una vez recibido un mensaje, invoca el método enviarMensaje de la clase Servidor con el fin de enviar dicho mensaje recibido a todos los clientes. El método enviar, se encarga de enviar al cliente asociado con el hilo, el mensaje recibido por parámetro.

Clase FCliente
001import java.awt.BorderLayout;
002import java.awt.event.ActionEvent;
003import java.awt.event.ActionListener;
004import java.io.IOException;
005import java.io.ObjectInputStream;
006import java.io.ObjectOutputStream;
007import java.net.InetAddress;
008import java.net.Socket;
009import java.net.UnknownHostException;
010import javax.swing.JButton;
011import javax.swing.JLabel;
012import javax.swing.JOptionPane;
013import javax.swing.JPanel;
014import javax.swing.JTextArea;
015import javax.swing.JTextField;
016import javax.swing.WindowConstants;
017import javax.swing.SwingUtilities;
018 
019public class FCliente extends javax.swing.JFrame {
020 private JPanel PConexion;
021 private JTextField TIP;
022 private JTextField TNombre;
023 private JButton BEnviar;
024 private JTextField TMensaje;
025 private JButton BConectar;
026 private JLabel LNombre;
027 private JLabel LIP;
028 private JTextArea TMensajes;
029 private JPanel PMensaje;
030 private Socket socket;
031 private HiloCliente hiloCliente;
032 private ObjectOutputStream output;
033 private ObjectInputStream input;
034 
035 public static void main(String[] args) {
036  SwingUtilities.invokeLater(new Runnable() {
037   public void run() {
038    FCliente inst = new FCliente();
039    inst.setLocationRelativeTo(null);
040    inst.setVisible(true);
041   }
042  });
043 }
044  
045 public FCliente() {
046  super();
047  initGUI();
048 }
049  
050 public JTextArea getTMensajes() {
051  return TMensajes;
052 }
053 
054 private void initGUI() {
055  try {
056   setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
057   BorderLayout thisLayout = new BorderLayout();
058   this.setTitle("Mini Chat. Cliente");
059   getContentPane().setLayout(thisLayout);
060   {
061    PConexion = new JPanel();
062    getContentPane().add(PConexion, BorderLayout.NORTH);
063    {
064     LIP = new JLabel();
065     PConexion.add(LIP);
066     LIP.setText("IP:");
067    }
068    {
069     TIP = new JTextField();
070     PConexion.add(TIP);
071     TIP.setText("127.0.0.1");
072    }
073    {
074     LNombre = new JLabel();
075     PConexion.add(LNombre);
076     LNombre.setText("Nombre Cliente");
077    }
078    {
079     TNombre = new JTextField();
080     PConexion.add(TNombre);
081     TNombre.setPreferredSize(new java.awt.Dimension(100, 20));
082     TNombre.setSize(100, 20);
083    }
084    {
085     BConectar = new JButton();
086     PConexion.add(BConectar);
087     BConectar.setText("Conectar");
088     BConectar.addActionListener(new ActionListener() {
089      public void actionPerformed(ActionEvent evt) {
090       BConectarActionPerformed(evt);
091      }
092     });
093    }
094   }
095   {
096    PMensaje = new JPanel();
097    BorderLayout PMensajeLayout = new BorderLayout();
098    PMensaje.setLayout(PMensajeLayout);
099    getContentPane().add(PMensaje, BorderLayout.SOUTH);
100    {
101     TMensaje = new JTextField();
102     PMensaje.add(TMensaje, BorderLayout.CENTER);
103     TMensaje.setEnabled(false);
104     TMensaje.setPreferredSize(new java.awt.Dimension(348, 21));
105    }
106    {
107     BEnviar = new JButton();
108     PMensaje.add(BEnviar, BorderLayout.EAST);
109     BEnviar.setText("Enviar");
110     BEnviar.addActionListener(new ActionListener() {
111      public void actionPerformed(ActionEvent evt) {
112       BEnviarActionPerformed(evt);
113      }
114     });
115     BEnviar.setEnabled(false);
116    }
117   }
118   {
119    TMensajes = new JTextArea();
120    getContentPane().add(TMensajes, BorderLayout.CENTER);
121   }
122   pack();
123   setSize(400, 300);
124  } catch (Exception e) {
125   e.printStackTrace();
126  }
127 }
128  
129 private void BConectarActionPerformed(ActionEvent evt) {
130  if(!this.TNombre.getText().equals("")){
131   try {
132    this.socket = new Socket(InetAddress.getByName(this.TIP.getText()),5000);
133    this.output = new ObjectOutputStream(this.socket.getOutputStream());
134    this.input = new ObjectInputStream(this.socket.getInputStream());
135    this.output.writeObject(this.TNombre.getText());
136    this.output.flush();     
137    this.hiloCliente = new HiloCliente(this,this.input);
138    this.hiloCliente.start();
139    this.BConectar.setEnabled(false);
140    this.TNombre.setEnabled(false);
141    this.TIP.setEnabled(false);
142    this.TMensaje.setEnabled(true);
143    this.BEnviar.setEnabled(true);
144   } catch (UnknownHostException e) {
145    JOptionPane.showMessageDialog(this,"Error de servidor","Error",JOptionPane.ERROR_MESSAGE);
146   } catch (IOException e) {
147    JOptionPane.showMessageDialog(this,"Error de servidor","Error",JOptionPane.ERROR_MESSAGE);
148   }    
149  }else{
150   JOptionPane.showMessageDialog(this, "Inserte Nombre","Error",JOptionPane.ERROR_MESSAGE);
151  }
152   
153 }
154  
155 private void BEnviarActionPerformed(ActionEvent evt) {
156  try {
157   this.output.writeObject(this.TMensaje.getText());
158   this.output.flush(); 
159  } catch (IOException e) {
160   e.printStackTrace();
161  }
162  this.TMensaje.setText(""); 
163 }
164}

La clase FCliente, es un JFrame que ejecuta el cliente, para enviar y recibir mensajes del servidor. Este Frame, contiene un cuadro de texto para ingresar la dirección IP donde se ubica el servidor, un cuadro de texto para ingresar el nombre del cliente, un botón Conectar para realizar la conexión con el servidor, un cuadro de texto para que el cliente digite el mensaje que desea enviar, un botón que envía el mensaje del cuadro de texto anterior y un área de texto que permite incluir los mensajes recibidos.Al ejecutar el cliente, se presenta el siguiente JFrame

El método BConectarActionPerformed se invoca al hacer clic en el botón conectar y efectúa la conexión con el servidor a través de un socket indicando la dirección IP del servidor y puerto de la aplicación. Una vez el servidor atiende la conexión, se crea el Stream de entrada, el Stream de salida y el hilo del cliente.El método BEnviarActionPerformed, envía información al servidor a través del Stream de salida obtenido por el socket en el cliente.

Clase HiloCliente
01import java.io.IOException;
02import java.io.ObjectInputStream;
03 
04public class HiloCliente extends Thread {
05 private ObjectInputStream input;
06 private FCliente cliente;
07 private boolean activo=true;
08 
09 public HiloCliente(FCliente cliente,ObjectInputStream input) {
10  this.cliente=cliente;
11  this.input=input; 
12 }
13  
14 public void run(){
15  while(this.activo){
16   String mensaje;
17   try {
18    mensaje = (String)this.input.readObject();
19    this.cliente.getTMensajes().append(mensaje+"\n");     
20   } catch (IOException e) {
21    this.activo=false;
22   } catch (ClassNotFoundException e) {
23    e.printStackTrace();
24   }
25  }
26 }
27}

En la clase HiloCliente, el método run se encarga de recibir mensajes del servidor. Una vez recibido un mensaje, lo coloca en el área de texto del Frame del cliente

Prueba de Chat

Al ejecutar el servidor, queda en espera de una conexión. Es importante anotar que el servidor se encuentra en la dirección IP 192.168.1.1. Presenta la siguiente información en consola.

Salida Estandar
1esperando nueva conexion

Al ejecutar un primer Cliente, se presenta el Frame de la figura anterior. Al ingresar un nombre de cliente y dar clic en el botón Conectar, se realiza la conexión de este cliente con el servidor y se presenta la notificación de conexión. En este caso, en el cliente uno se presenta el mensaje “Cliente uno se ha conectado”. El resultado se presenta en la siguiente figura

En el servidor se captura la información de dicho cliente. Se presenta la siguiente información en consola.

Salida Estandar
1Esperando nueva conexion
2Conexion 1 desde: HECTOR_1 IP: 192.168.1.2
3Cliente uno se ha conectado
4Esperando nueva conexion

Al ejecutar el segundo Cliente e ingresar un nombre de cliente y dar clic en el botón Conectar, se realiza la conexión de este cliente con el servidor y se presenta la notificación de conexión. En este caso, tanto en el cliente uno como en el cliente dos, se presenta el mensaje “Cliente dos se ha conectado”. El resultado se presenta en la siguiente figura.

En el servidor se captura la información de dicho cliente. Se presenta la siguiente información en consola.

Salida Estandar
1Esperando nueva conexion
2Conexion 1 desde: HECTOR_1 IP: 192.168.1.2
3Cliente uno se ha conectado
4Esperando nueva conexion
5Conexion 2 desde: HECTOR_2 IP: 192.168.1.3
6Cliente dos se ha conectado
7Esperando nueva conexion 

Al ejecutar el tercer Cliente e ingresar un nombre de cliente y dar clic en el botón Conectar, se realiza la conexión de este cliente con el servidor y se presenta la notificación de conexión. En este caso, tanto en el cliente uno como en el cliente dos como en el cliente tres, se presenta el mensaje “Cliente tres se ha conectado”. El resultado se presenta en la siguiente figura.

En el servidor se captura la información de dicho cliente. Se presenta la siguiente información en consola.

Salida Estandar
01Esperando nueva conexion
02Conexion 1 desde: HECTOR_1 IP: 192.168.1.2
03Cliente uno se ha conectado
04Esperando nueva conexion
05Conexion 2 desde: HECTOR_2 IP: 192.168.1.3
06Cliente dos se ha conectado
07Esperando nueva conexion
08Conexion 3 desde: HECTOR_3 IP: 192.168.1.4
09Cliente tres se ha conectado
10Esperando nueva conexion 

Al colocar un mensaje en el cuadro de texto inferior del cliente uno y dar clic en enviar, el servidor recibe dicho mensaje y lo reenvía a todos los clientes conectados. En el mensaje, el servidor agregar el texto “Cliente dice: ”, donde cliente hace referencia al nombre del cliente que envía el mensaje.

En el servidor se captura el mensaje enviado por el cliente uno, se visualiza en consola y se reenvía a todos los demás clientes. Se presenta la siguiente información en consola

Salida Estandar
01Esperando nueva conexion
02Conexion 1 desde: HECTOR_1 IP: 192.168.1.2
03Cliente uno se ha conectado
04Esperando nueva conexion
05Conexion 2 desde: HECTOR_2 IP: 192.168.1.3
06Cliente dos se ha conectado
07Esperando nueva conexion
08Conexion 3 desde: HECTOR_3 IP: 192.168.1.4
09Cliente tres se ha conectado
10Esperando nueva conexion
11Cliente uno dice: Hola mundo 

Al colocar un mensaje en el cuadro de texto inferior del cliente dos y dar clic en enviar, el servidor recibe dicho mensaje y lo reenvía a todos los clientes conectados de la misma forma que se realizó el proceso con el cliente uno.

En el servidor se captura el mensaje enviado por el cliente uno, se visualiza en consola y se reenvía a todos los demás clientes. Se presenta la siguiente información en consola.

Salida Estandar
01Esperando nueva conexion
02Conexion 1 desde: HECTOR_1 IP: 192.168.1.2
03Cliente uno se ha conectado
04Esperando nueva conexion
05Conexion 2 desde: HECTOR_2 IP: 192.168.1.3
06Cliente dos se ha conectado
07Esperando nueva conexion
08Conexion 3 desde: HECTOR_3 IP: 192.168.1.4
09Cliente tres se ha conectado
10Esperando nueva conexion
11Cliente uno dice: Hola mundo
12Cliente dos dice: Hola Planeta Tierra

8 comentarios:

  1. Profe gracias, que buen tutorial

    ResponderEliminar
  2. profe una pregunta en caso de querer hacer la comunicación con redes remotas se debe usar IP Publicas? ¿como seria el proceso? gracias

    ResponderEliminar
    Respuestas
    1. Si se requiere IP publica.. En el cliente, simplemente se coloca dicha direccion IP publica.

      Eliminar
  3. me gustaría hacer una aplicación para controlar remotamente la propiedad setEnabled de un jbutton se podrá esto?

    ResponderEliminar
    Respuestas
    1. Para este caso, el mensaje debe incluir un valor que identifique esta funcionalidad. En el ejemplo presentado solo se envían mensajes de texto. Lo mejor es crear una clase serializable (Ej. ButtonControler.java) que contenga un atributo que controle el JButton (Ej. setEnabled). En el cliente, se debe crear una instancia de dicha clase (ButtonControler) y se asigna el valor del atributo (setEnable=true). En el servidor se debe recibir el objeto serializado y se hace casting con la clase (ButtonControler). Finalmente, puede consultar el valor del atributo

      Eliminar