Atom Blog

Como Hacer un Chat con Sockets en Java en Netbeans


En este nuevo post mostraremos como hacer un chat mediante el uso de Sockets en Java en el ambiente de programacion Netbeans. Los Sockets sirven para comunicar procesos de diferentes maquinas de una red.

Haremos un servidor y un cliente utilizando Sockets.

Del lado del Servidor se tiene un bucle infinito que espera conexiones de clientes. Cuando un cliente se conecta el servidor acepta la conexion 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 identica a la clase principal del cliente; la unica diferencia esta 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 maquina.

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) estan determinados por la IANA (Internet Assigned Numbers Authority). y no se los puede utilizar de otro 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 identicos para envio y recepcion de datos.

Empezaremos describiendo las clases del lado del servidor:

Clase PrincipalChat:
Esta clase implementa la interfaz grafica para poder mostrar los mensajes entrantes y un JTextField para poder enviarlos. La interfaz contiene un menu para poder salir del programa.
En el main se puede ver que se espera conexiones de clientes.


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 metodo enviarDatos().
Ademas declaramos la variable conexion tipo Socket, la cual se encarga de establecer el flujo de datos entre  cliente y servidor.

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.
Aqui 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 conexion una vez finalizado el flujo de datos.

En el paquete Cliente encontramos:

Clase PrincipalChat:
Esta clase implementa la interfaz grafica para poder mostrar los mensajes entrantes y un JTextField para poder enviarlos. La interfaz contiene un menu para poder salir del programa.
Esta clase busca servidores para poder conectarse.

Las clases descritas en el paquete Cliente: ThreadRecibe y ThreadEnvia son exactamente las mismas que se describieron en el paquete Servidor.

Nuestro proyecto se vera asi:


El resultado final se mostrara de la siguiente manera:

Para descargar el proyecto completo click en la siguiente imagen:

Skydrive

Dropbox







100 comentarios:

  1. La case PrincipalChat para el cliente cual es?

    ResponderBorrar
    Respuestas
    1. Hola que tal! la segunda "Clase PrincipalChat" es la destinada para el cliente.

      Borrar
    2. y para agregarle emotics no tienes o no tienes codigo de eso???

      Borrar
  2. Respuestas
    1. Debes tener abierto el hotmail para poder descargar el proyecto!

      Borrar
  3. Si necesitara que el cliente se encontrara en un pc independiente al servidor, que modificaciones debería hacer? agradecería mucho tu ayuda.

    ResponderBorrar
    Respuestas
    1. Las modificaciones deben hacerse tanto del lado del servidor como de cliente. Se debe cambiar la ip y abrir puertos de entrada y salida en ambos casos.

      Servidor: Clase PrincipalChat
      linea 27: cambiar la ip 127.0.0.1 por la ip de la pc a la que se desea conectar.
      linea 85: cambiar el puerto 11111 por el puerto que abrio en servidor.

      Cliente: Clase PrincipalChat
      linea 28: cambiar la ip 127.0.0.1 por la ip de la pc a la que se desea conectar.
      linea 87: cambiar el puerto 11111 por el puerto que se abrio en el cliente.

      Los puertos abiertos en el servidor y en el cliente deben ser los mismos.

      Para saber como abrir puertos seguir el siguiente link:
      http://ofeewds.blogspot.com/2012/09/como-abrir-puertos-de-entrada-y-salida.html

      Borrar
    2. el código está muy bien, ¿pero como se podría hacer que se pida un Nick al entrar?, luego si son dos clientes no hay problema al hablar cliente-servidor pero si se conectan varios clientes ¿como un cliente direcciona el mensaje a otro? o como un cliente manda un mensaje al resto como broadcast, los mensajes desde el servidor si llegan al resto de clientes pero los de los cliente solo llegan al servidor y no entre ellos.

      Gracias de antemano.

      Borrar
    3. Hola que tal!
      Para tu primera pregunta: aqui un chat que pide un nick al entrar.
      https://skydrive.live.com/#cid=CB2C976AE9CB5D07&id=CB2C976AE9CB5D07%21280

      Se ha creado un metodo ingresarNick(), el cual pide un nick al entrar al programa y es llamado desde el main.

      Respecto a tu segunda pregunta: pido disculpas, no he realizado un programa asi!

      Borrar
    4. Ok gracias, veré lo de ingresar el Nick, lo del envío a todos los clientes es ver como manejar los hilos de envío y recibo de mensajes metiendo un Id por cliente, si averiguo como hacerlo, meto el código.

      Borrar
    5. Hola quiero conectar en otra pc...es necesario cambiar los puertos 11111.... no entendi como abrir los puertos...el enlace que pones no esta disponible

      Borrar
  4. Este comentario ha sido eliminado por el autor.

    ResponderBorrar
  5. oie men dice ke el archivo a sido eliminado o a expirado no lo puedes subir otravez por fa hermano espero i me pudas ayudar gracias

    ResponderBorrar
  6. oye bro con todo y mi cuenta de hotmail abierta y con todo y mi skydrive abierto me dice que no puedo acceder al archivo que es posible que haya sido movido o eliminado

    ResponderBorrar
    Respuestas
    1. Es muy extrano que te aparezca eso! comprobé y el enlace funciona.
      Con todo acabo de actualizar el link de descarga.
      Además agregué otro enlace por si el primero no te funciona!

      Saludos!

      Borrar
  7. como lo integro a mi una pagina web '? se podra

    ResponderBorrar
    Respuestas
    1. Aqui una guia que te podria sevir!

      www.solotuweb.com/fs~id~10451.html

      Borrar
  8. Hola Rafa Gallardo, Tendras el codigo por ahi, para un nuevo thread para realizar videollamada tambien ?

    ResponderBorrar
  9. Hola, estoy intentando ejecutar el programa con 2 pc conectados a la misma red, ya cambie lo de la ip y lo de los puertos, y sigue sin funcionar, que otro cambio puedo hacer para que funcione?

    ResponderBorrar
    Respuestas
    1. Tienes que bajar los firewalls en ambas computadoras!

      Borrar
    2. Tampoco me funciono, me aparece lo siguiente:

      SEVERE: null
      java.net.ConnectException: Connection refused: connect
      at java.net.DualStackPlainSocketImpl.connect0(Native Method)
      at java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:69)
      at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:339)
      at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:200)
      at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:182)
      at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:157)
      at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:391)
      at java.net.Socket.connect(Socket.java:579)
      at java.net.Socket.connect(Socket.java:528)
      at java.net.Socket.(Socket.java:425)
      at java.net.Socket.(Socket.java:241)
      at cliente.PrincipalChat.main(PrincipalChat.java:87)

      Borrar
    3. Hola Rafa Gallardo, tengo el mismo problema que Rafael, cuando ejecuto el programa en el mismo computador funciona bien, pero cuando lo hago con dos computadores diferente nada; hice el cambio de la ip y cree los puertos...

      Borrar
  10. Hola Rafa Gallardo, tengo el mismo problema que Rafael, cuando ejecuto el programa en el mismo computador funciona bien, pero cuando lo hago con dos computadores diferente nada; hice el cambio de la ip y cree los puertos...

    ResponderBorrar
  11. Hola! A los mejor el antivirus no les permite conectarse! desactivenlo al igual q los firewalls!
    Tienen que que iniciar primero el servidor y después el cliente!

    ResponderBorrar
  12. Asegúrense de haber cambiado correctamente los puertos e IPs en los lugares que se pide. El programa se ha probado y funciona correctamente.

    ResponderBorrar
  13. men disculpa pero lo corro en jcpro y me da error no se a encontrado la clase principal servidor

    ResponderBorrar
  14. men me da dos errores ayi axulio como hago

    executor.execute(new ThreadRecibe(conexion, main)); //client
    executor.execute(new ThreadEnvia(conexion, main));

    ResponderBorrar
  15. Men no entiendo como correrlo mira lo q me dice cuando corro el cliente


    --------------------Configuration: --------------------
    C:\Users\SuperMan\Desktop\ChatSockets\src\cliente\PrincipalChat.java:94: error: cannot find symbol
    executor.execute(new ThreadRecibe(cliente, main));
    ^
    symbol: class ThreadRecibe
    location: class PrincipalChat
    C:\Users\SuperMan\Desktop\ChatSockets\src\cliente\PrincipalChat.java:95: error: cannot find symbol
    executor.execute(new ThreadEnvia(cliente, main));
    ^
    symbol: class ThreadEnvia
    location: class PrincipalChat
    2 errors

    Process completed.

    ResponderBorrar
  16. no ya listo men pero necesito que envié archivos entiendes

    ResponderBorrar
  17. Hola Rafa, a mi tampoco me funciona cuando intento conectar dos PC conectados al mismo router mediante wifi. Tengo los puertos de ambas computadoras abiertas así como los del router. Introduzco en la clase PrincipalChat del cliente la ip interna del servidor, alguna idea?

    Muchas gracias y muy buen post!

    ResponderBorrar
  18. por favor serias tan amable de publicar nuevamente el ejemplo que permite agregar un nick?
    muchas gracias :D

    ResponderBorrar
    Respuestas
    1. seguro! aqui el link! https://www.dropbox.com/s/fwx6urp7rn6x9ol/ChatSocketsElegirNick.rar

      Borrar
  19. Necesito de su ayuda..Pero necesito hacer un chat pero cuando cualquiera de los dos escriba salir o terminar
    Se acabe la conexion..URGENTE

    ResponderBorrar
  20. Hola no me muestra la imagen que tu colocaste es decir la de conectado al servidor y no puedo chatear(escribir) nada me podrias ayudar si tengo que modificar algo mas dentro de tu archivo...

    ResponderBorrar
    Respuestas
    1. que tal!! si vas a correr en la misma compu no tienes que modificar absolutamente nada.
      Pero si vas a correr en dos computadoras distintas debes de abrir los puertos (entrada y salida) y modificar las IPs. Ademas bajar los firewalls y desactivar el antivirus.

      Borrar
  21. hola una pregunta como le puedo ahcer para conectarlo con dos computadoras es que no le entiendo mucho

    ResponderBorrar
  22. tienes que abrir puertos de entrada y salida en ambas pcs! Luego debes de cambiar la IP (127.0.0.1) por la IP de la Pc a la que te deseas conectar.
    Ademas tienes que desactivar el antivirus y bajar los firewalls para poder conectarte.

    ResponderBorrar
  23. Hola Rafa, tengo una duda, como modificarias la clase ChatPrincipal del paquete cliente de tal manera que se puedan crear varios clientes y todos puedan conectarse o desconectarse del servido?

    ResponderBorrar
    Respuestas
    1. hola q tal! si recuerdo bien, este programa permite ejecutar varios clientes q se conectan al sevidor.
      Primero ejecutas el servidor y luego ejecutas el cliente cuantas veces desees!!

      Borrar
  24. Me sale este error cuando corro el cliente
    ava.net.BindException: Address already in use: JVM_Bind
    at java.net.PlainSocketImpl.socketBind(Native Method)
    at java.net.PlainSocketImpl.bind(PlainSocketImpl.java:383)
    at java.net.ServerSocket.bind(ServerSocket.java:328)
    at java.net.ServerSocket.(ServerSocket.java:194)
    at java.net.ServerSocket.(ServerSocket.java:150)
    at servidor.PrincipalChat.main(PrincipalChat.java:86)

    Desconecte firewall y antivirus, como lo puedo solucionar?

    ResponderBorrar
  25. hey man muy bue tuto yo tambien soy programador deberias agregarme en facbeook y hablamos un rato (Y)
    https://www.facebook.com/david.st.rock

    ResponderBorrar
  26. Muy bueno está de 10 el ejemplo, saludos.

    ResponderBorrar
  27. amigo puedo llamar ese metodo desde un boton en una interfaz para un proyecto que estoy realizando? osea apretar el boton y que aparezca el chat.

    ResponderBorrar
    Respuestas
    1. claro! solo debes crearte otra ventana para que puedas llamar al chat

      Borrar
  28. me sale error en el servidor en la siguiente
    executor.execute(new Recibe(conexion, main)); //client
    executor.execute(new Envia(conexion, main));

    ResponderBorrar
  29. Gracias Excelente aporte, me ha servido de maravilla

    ResponderBorrar
  30. Hola! Necesito ayuda con un programa similar. ¿Hay alguien ahí?

    ResponderBorrar
  31. hola me gustó,me ah funcionado el chat que hiciste y me a servido para una clase en mi universidad, me gustaria como seria para que ese mismo chat se pueda o permita enviar archivo. que sea con archivos adjuntados

    ResponderBorrar
  32. hola necesito ayuda con el mismo chat, aparte del chat necesito que se pueda enviar o adjuntar archivos para ese mismo ejercicio que estas publicando del chat con sockets

    ResponderBorrar
    Respuestas
    1. me alegra que te sirviera! para poder enviar archivos desde el chat debes de crear algun boton que se llame "enviar archivo" y llamar a la clase thread EnviarArchivo que te adjunto en el sig link https://www.dropbox.com/s/vtoimt7mxrzg72u/EnviarArchivo.java. Ademas debes ajuntar la clase thread RecibirArchivo https://www.dropbox.com/s/ge0vzg8ivyl57lc/RecibirArchivo.java. Ambos threads debes de ejecutarlos desde la clase PrincipalChat en la seccion "ejecucion de threads" de la siguiente manera: executor.execute(new RecibirArchivo()); y executor.execute(new EnviarArchivo(main));

      Borrar
    2. ok gracias, voy a ver como me va si algo te esterare preguntando de nuevo, por si algo ese te mi correo juanchopolo170@gmail.com y mi skype juanchopolo170

      Borrar
    3. afa podemos hablar por skype quisiera hacer mas preguntas sobre el chat con sockets mi skype es juanchopolo170

      Borrar
    4. Si te sirve aquí tienes lo que deseas.

      http://todoenjava.blogspot.com/2013/05/chat-y-transferencia-de-archivos.html

      Borrar
  33. Carolina Yumbay30 de octubre de 2013, 8:30

    me sale error en el servidor en la siguiente
    executor.execute(new Recibe(conexion, main)); //client
    executor.execute(new Envia(conexion, main));

    Me pasa lo mismo.
    Pues no entiendo?? No existe ningún constructor con los nombres Recibe ni Envía, quizás debieran ser ThreadRecibe y ThreadEnvía, pero tampoco. He revisado todo el hilo y no encuentro la solución al problema.
    Muy bueno, pero me he quedado a trancas.

    ResponderBorrar
  34. Este comentario ha sido eliminado por el autor.

    ResponderBorrar
  35. excelente rafa!! oye para agregar un segundo cliente?

    ResponderBorrar
    Respuestas
    1. Aquí un ejemplo...

      http://todoenjava.blogspot.com/2013/05/chat-y-transferencia-de-archivos.html

      Borrar
  36. que tal rafa, hay un refrán que dice que las cosas son verdaderamente tuyas hasta que las compartes...

    gracias por el código, servirá para el proyecto de la facultad...
    :O)

    ResponderBorrar
  37. OIE AMIGO Y COMO SERIA SI QUISIERA MANDAR MENSAJES DE CLIENTE A CLIENTE ???????

    ResponderBorrar
    Respuestas
    1. aquí tienes un ejemplo de eso...

      http://todoenjava.blogspot.com/2013/05/chat-y-transferencia-de-archivos.html

      Borrar
  38. Aquí les comparte un chat multiusuario con transferencia de archivos; el chat en cliente servidor y la transferencia de archivos en P2P, el código se encuentra ahí mismo. También se pueden suscribir al blog.

    Saludos.

    http://todoenjava.blogspot.com/2013/05/chat-y-transferencia-de-archivos.html

    ResponderBorrar
  39. Este comentario ha sido eliminado por el autor.

    ResponderBorrar
  40. DISCULPA AL ESCRIBIR "TERMINATE" NO TERMINA LA CONEXION, PORQUE PODRA SER?

    ResponderBorrar
  41. Como adjuntar archivos en este chat, algun metodo o pack destinado para lo mismo?

    ResponderBorrar
  42. oyes ami nadamas me parese "esperando cliente......"

    ResponderBorrar
  43. Hola que tal hice una aplicacion similar de cliente servidor pero solo funciona en redes locales lan quisiera saber de que manera y que puertos debo utilizar para realizar el chat por internet de casa a casa , desde ya muchas gracias :D

    ResponderBorrar
  44. Hola una pregunta para enviar mensajes y despues archivos como se lograria esto en el mismo socket.

    ResponderBorrar
  45. hola disculpa y para poder chatear con alguien que esta en otra ciudad que yo como haria ? necesito tu ayuda porfavor

    ResponderBorrar
  46. Buenas Rafa como vamos.....oye tenia una pregunta al momento de ejecutar la parte del cliente me aparecen estas tres lineas de error

    Exception in thread "main" java.lang.UnsupportedOperationException: Not supported yet.
    at cliente.ThreadRecibe.(ThreadRecibe.java:41)
    at cliente.PrincipalChat.main(PrincipalChat.java:94)

    podrias asesorarme en eso ? Gracias

    ResponderBorrar
  47. Hola amigo tengo una pregunta..
    Se puede conectar a dos computadoras que no estén en la misma red?

    ResponderBorrar
  48. Excelente trabajo amigo, muchas gracias, saludos

    ResponderBorrar
  49. me sale este error, me podrian ayudar por favor?

    java.net.BindException: Address already in use: JVM_Bind
    at java.net.DualStackPlainSocketImpl.bind0(Native Method)
    at java.net.DualStackPlainSocketImpl.socketBind(DualStackPlainSocketImpl.java:106)
    at java.net.AbstractPlainSocketImpl.bind(AbstractPlainSocketImpl.java:387)
    at java.net.PlainSocketImpl.bind(PlainSocketImpl.java:190)
    at java.net.ServerSocket.bind(ServerSocket.java:375)
    at java.net.ServerSocket.(ServerSocket.java:237)
    at java.net.ServerSocket.(ServerSocket.java:181)
    at servidor.PrincipalChat.main(PrincipalChat.java:96)

    ResponderBorrar
  50. como le puedo hacer para descargarlo no me permite porfavor

    ResponderBorrar
  51. Muchas gracias por el proyecto, me ha sido de mucha ayuda. Yo le hice unos pequeños cambios para que funcionara como un chat de grupo.

    ResponderBorrar
    Respuestas
    1. Jorge me gustaria tu ayuda para un proyecto que debo hacer con un chat de grupo o multihilos

      Borrar
  52. Que programas necesito específicamente?

    ResponderBorrar
  53. Hola como llamo las clases com um boton? Es decir al presionar el boton que ejecute cliente y servidor puesto que abre ventanas pero no corre...

    ResponderBorrar
  54. disculpa me podria explicar bien como implementarlo y utlizarlo , la conexion con el ip y el server , no la entiendo.

    ResponderBorrar
  55. hola amigo... gracias por el aporte, sabes como hacerlo para que sea multi-usuarios

    ResponderBorrar
  56. Hola, disculpa , cual es la contraseña ?

    ResponderBorrar
  57. Increíble aporte amigo! Me ha servido de mucho! Gracias

    ResponderBorrar
  58. Gracias; sin duda este fue el unico que me ayudo. Grcias

    ResponderBorrar
  59. Hola. Muchas gracias por tu aporte. Salvaste mi cuatrimestre. Sos un crack.

    ResponderBorrar
  60. gracias por la ayuda me salvaste del plan de mejoramiento

    ResponderBorrar
  61. Para los que les marca error de que la dirección ya esta en uso es porque están corriendo dos veces el servidor lo que tienen que hacer es correr primero el programa de ahí dar clic derecho al proyecto y dirigirse a propiedades de ahí buscan la opción donde diga run y cambiar a clase del servidor por la del cliente lo corren obvio sin cerrar la ventana del servidor y listo ya funcionara y para volver a correrlo tienen que hacer lo mismo pero a la inversa recuerden que primero se corre el servidor y después el cliente

    ResponderBorrar
  62. Gracias por tu aporte esta muy completo y entendible.

    ResponderBorrar
  63. Una pregunta cómo podría hacerle para enviar un mensaje desde el servidor a un cliente en específico

    ResponderBorrar