Académique Documents
Professionnel Documents
Culture Documents
En este nuevo post mostraremos como hacer un chat mediante el uso de Sockets en Java en el ambiente de programación
Netbeans. Los Sockets sirven para comunicar procesos de diferentes máquinas de una red.
Del lado del Servidor se tiene un bucle infinito que espera conexiones de clientes. Cuando un cliente se conecta el servidor
acepta la conexión y genera dos threads: uno para enviar datos y el otro para recibirlos.
Del lado del Cliente se tiene que esperar un Servidor para poder conectarse, cuando se conecta al servidor se generan
dos threads, al igual que en el Servidor uno para enviar y otro para recibir los datos.
Los threads que se generan del lado del servidor y del cliente son los mismos.
La clase principal del Servidor es idéntica a la clase principal del cliente; la única diferencia está en el main, el servidor
espera conexiones del cliente y el cliente busca servidor para conectarse.
Para nuestro ejemplo utilizaremos localhost para poder correr el programa en nuestra propia máquina.
Es importante tener en cuenta que puerto se va a utilizar para poder abrirlo con anterioridad, en nuestro caso abriremos
el puerto 11111.
Se debe conocer que las asignaciones a los puertos comprendidos entre los valores (0 - 1023) están determinados por
la IANA (Internet Assigned Numbers Authority). y no se los puede utilizar de otra manera.
Se puede utilizar los puertos comprendidos entre los valores (1024 - 65535).
Nuestro programa cuenta con dos paquetes, uno para el servidor y otro para el cliente; los mismo que contiene threads
idénticos para envío y recepción de datos.
Clase PrincipalChat:
Esta clase implementa la interfaz gráfica para poder mostrar los mensajes entrantes y un JTextField para poder enviarlos.
La interfaz contiene un menú para poder salir del programa.
1
Mg. Freddy Toribio Huayta Meza
2
Mg. Freddy Toribio Huayta Meza
3
Mg. Freddy Toribio Huayta Meza
106. }
107. executor.shutdown();
108. }
109. }
Clase ThreadEnvia:
En esta clase establecemos nuestro canal de salida tipo ObjectOutputStream, el cual nos sirve para escribir el
mensaje, enviarlo y mostrarlo en pantalla mediante el método enviarDatos().
Además, declaramos la variable conexión tipo Socket, la cual se encarga de establecer el flujo de datos entre
cliente y servidor.
1. package servidor;
2. import java.io.IOException;
3. import java.io.ObjectOutputStream;
4. import java.net.Socket;
5. import java.awt.event.ActionEvent;
6. import java.awt.event.ActionListener;
7. import java.net.SocketException;
8.
9. public class ThreadEnvia implements Runnable {
10. private final PrincipalChat main;
11. private ObjectOutputStream salida;
12. private String mensaje;
13. private Socket conexion;
14.
15. public ThreadEnvia(Socket conexion, final PrincipalChat main){
16. this.conexion = conexion;
17. this.main = main;
18.
19. //Evento que ocurre al escribir en el areaTexto
20. main.campoTexto.addActionListener(new ActionListener() {
21. public void actionPerformed(ActionEvent event) {
22. mensaje = event.getActionCommand();
23. enviarDatos(mensaje); //se envia el mensaje
24. main.campoTexto.setText(""); //borra el texto del enterfield
25. } //Fin metodo actionPerformed
26. }
27. );//Fin llamada a addActionListener
28. }
29.
30. //enviar objeto a cliente
31. private void enviarDatos(String mensaje){
32. try {
33. salida.writeObject("Servidor>>> " + mensaje);
34. salida.flush(); //flush salida a cliente
35. main.mostrarMensaje("Servidor>>> " + mensaje);
36. } //Fin try
4
Mg. Freddy Toribio Huayta Meza
Clase ThreadRecibe:
En esta clase establecemos nuestro canal de entrada tipo ObjectInputStream, el cual se encarga de recibir los mensajes
enviados por el cliente o servidor.
Aquí se procesa los mensajes recibidos y luego son mostrados en pantalla.
Es importante aclarar que se debe cerrar el canal de entrada de datos y el Socket de conexión una vez finalizado el flujo
de datos.
1. package servidor;
2. import java.io.EOFException;
3. import java.io.IOException;
4. import java.io.ObjectInputStream;
5. import java.net.Socket;
6. import java.net.SocketException;
7. import java.util.logging.Level;
8. import java.util.logging.Logger;
9.
10. public class ThreadRecibe implements Runnable {
11. private final PrincipalChat main;
12. private String mensaje;
13. private ObjectInputStream entrada;
14. private Socket cliente;
15.
5
Mg. Freddy Toribio Huayta Meza
16.
17. //Inicializar chatServer y configurar GUI
18. public ThreadRecibe(Socket cliente, PrincipalChat main){
19. this.cliente = cliente;
20. this.main = main;
21. }
22.
23. public void mostrarMensaje(String mensaje) {
24. main.areaTexto.append(mensaje);
25. }
26.
27. public void run() {
28. try {
29. entrada = new ObjectInputStream(cliente.getInputStream());
30. } catch (IOException ex) {
31. Logger.getLogger(ThreadRecibe.class.getName()).log(Level.SEVERE, null, ex);
32. }
33. do { //procesa los mensajes enviados dsd el servidor
34. try {//leer el mensaje y mostrarlo
35. mensaje = (String) entrada.readObject(); //leer nuevo mensaje
36. main.mostrarMensaje(mensaje);
37. } //fin try
38. catch (SocketException ex) {
39. }
40. catch (EOFException eofException) {
41. main.mostrarMensaje("Fin de la conexion");
42. break;
43. } //fin catch
44. catch (IOException ex) {
45. Logger.getLogger(ThreadRecibe.class.getName()).log(Level.SEVERE, null, ex);
46. } catch (ClassNotFoundException classNotFoundException) {
47. main.mostrarMensaje("Objeto desconocido");
48. } //fin catch
49.
50. } while (!mensaje.equals("Servidor>>> TERMINATE")); //Ejecuta hasta que el server
escriba TERMINATE
51.
52. try {
53. entrada.close(); //cierra input Stream
54. cliente.close(); //cieraa Socket
55. } //Fin try
56. catch (IOException ioException) {
57. ioException.printStackTrace();
58. } //fin catch
59.
60. main.mostrarMensaje("Fin de la conexion");
6
Mg. Freddy Toribio Huayta Meza
61. System.exit(0);
62. }
63. }
1. package cliente;
2. import java.awt.BorderLayout;
3. import java.awt.Color;
4. import java.awt.event.ActionEvent;
5. import java.awt.event.ActionListener;
6. import java.io.EOFException;
7. import java.io.IOException;
8. import java.net.InetAddress;
9. import java.net.ServerSocket;
10. import java.net.Socket;
11. import java.util.concurrent.ExecutorService;
12. import java.util.concurrent.Executors;
13. import java.util.logging.Level;
14. import java.util.logging.Logger;
15. import javax.swing.*;
16.
17. /**Clase que se encarga de correr los threads de enviar y recibir texto
18. * y de crear la interfaz grafica.
19. */
20. public class PrincipalChat extends JFrame{
21. public JTextField campoTexto; //Para mostrar mensajes de los usuarios
22. public JTextArea areaTexto; //Para ingresar mensaje a enviar
23. private static ServerSocket servidor; //
24. private static Socket cliente; //Socket para conectarse con el cliente
25. private static String ip = "127.0.0.1"; //ip a la cual se conecta
26.
27. public static PrincipalChat main;
28.
29. public PrincipalChat(){
30. super("Cliente"); //Establece titulo al Frame
31.
32. campoTexto = new JTextField(); //crea el campo para texto
33. campoTexto.setEditable(false); //No permite que sea editable el campo de texto
34. add(campoTexto, BorderLayout.NORTH); //Coloca el campo de texto en la parte superior
35.
36.
7
Mg. Freddy Toribio Huayta Meza
8
Mg. Freddy Toribio Huayta Meza
Las clases descritas en el paquete Cliente: ThreadRecibe y ThreadEnvia son exactamente las mismas que
se describieron en el paquete Servidor.
9
Mg. Freddy Toribio Huayta Meza
Los sockets son básicamente formas en las que podemos interconectar 2 (o mas) programas mediante el uso de la
internet. En java se utilizan para poder crear conexiones utilizando basicamente una IP/hostname y un puerto para
establecer la conexión. Para aprender podemos utilizarla para conenctar 2 programas por medio de Internet.
¿Como funciona?
El modelo más básico de los sockets consta de 2 simples programas, un servidor y un cliente. Basicamente el programa
servidor comienza a “escuchar” en un puerto determinado (nosotros lo especificamos), y posteriormente el programa que
la hace de “cliente” debe conocer la ip o nombre de dominio/hostname del servidor y el puerto que esta escuchando, al
saber esto simplemente solicita establecer una conexión con el servidor. Es aqui cuando el servidor acepta esa conexión
y se puede decir que estos programas estan “conectados”, de este modo pueden intercambiar información. En el siguiente
video muestro un programa servidor con sockets, explico mas o menos el codigo, en que consiste y hago una prueba en
el cual la conexión es exitosa.
Notas:
* Ambos programas (servidor y cliente) no necesitan estar programados en Java, es posible programarlos en lenguajes
de programación diferentes, o inclusive programar un servidor en java y utilizar un cliente ya existente que pueda
conectarse a un puerto especificado.
* El cliente debe de conocer tanto el puerto a utilizar como la IP o dominio del servidor, mientras el servidor solo debe
conocer el puerto de conexión
A continuación, se presenta el código en java de un servidor muy simple, lo que hace es escuchar el puerto 5000, cuando
un cliente se conecta este envía un mensaje de confirmación al cliente, luego el cliente al enviar su primer mensaje, el
servidor envía un segundo mensaje y se cierra la conexión. También el de un cliente muy simple solo para que se vea la
diferencia, de como se pide la conexión al servidor, el cliente únicamente envía un mensaje de texto, pero no recibe
información.
import java.net.*;
import java.io.*;
ServerSocket sc;
Socket so;
DataOutputStream salida;
String mensajeRecibido;
//SERVIDOR
BufferedReader entrada;
10
Mg. Freddy Toribio Huayta Meza
try
sc = new ServerSocket(PUERTO );/* crea socket servidor que escuchara en puerto 5000*/
so=new Socket();
so = sc.accept();
//Inicia el socket, ahora esta esperando una conexión por parte del cliente
//Recepcion de mensaje
mensajeRecibido = entrada.readLine();
System.out.println(mensajeRecibido);
System.out.println("Cerrando conexión...");
} catch(Exception e )
System.out.println("Error: "+e.getMessage());
view source
11
Mg. Freddy Toribio Huayta Meza
import java.net.*;
import java.io.*;
Socket sc;
DataOutputStream mensaje;
DataInputStream entrada;
//Cliente
try
sc = new Socket( HOST , PUERTO ); /*conectar a un servidor en localhost con puerto 5000*/
//enviamos el mensaje
//cerramos la conexión
sc.close();
} catch(Exception e )
System.out.println("Error: "+e.getMessage());
12