Main

Translate

martes, 31 de julio de 2012

Como Hacer un Chat con Sockets en Java


En este nuevo post mostraremos como hacer un chat mediante el uso de Sockets en Java. 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







74 comentarios:

  1. La case PrincipalChat para el cliente cual es?

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

      Eliminar
  2. El proyecto no se deja descargar amigo

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

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

    ResponderEliminar
    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

      Eliminar
    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.

      Eliminar
    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!

      Eliminar
    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.

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

    ResponderEliminar
  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

    ResponderEliminar
    Respuestas
    1. El enlace de descarga funciona perfectamente.
      Para poder ingresar a la descarga debes tener abierta una cuenta de hotmail!

      Saludos!!

      Eliminar
  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

    ResponderEliminar
    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!

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

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

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

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

    ResponderEliminar
    Respuestas
    1. Hola Yull! Lamentablemente no tengo un código así.

      Eliminar
  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?

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

      Eliminar
    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)

      Eliminar
    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...

      Eliminar
  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...

    ResponderEliminar
  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!

    ResponderEliminar
  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.

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

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

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

    ResponderEliminar
    Respuestas
    1. Si estas ejecutando el servidor antes de ejecutar el cliente?

      Eliminar
  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.

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

    ResponderEliminar
  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!

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

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

      Eliminar
  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

    ResponderEliminar
  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...

    ResponderEliminar
    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.

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

    ResponderEliminar
  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.

    ResponderEliminar
  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?

    ResponderEliminar
    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!!

      Eliminar
  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?

    ResponderEliminar
  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

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

    ResponderEliminar
  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.

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

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

    ResponderEliminar
    Respuestas
    1. Revisen las sugerencias que he ido poniendo a lo largo de los comentarios!!

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

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

    ResponderEliminar
  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

    ResponderEliminar
  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

    ResponderEliminar
    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));

      Eliminar
    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

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

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

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

      Eliminar
  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.

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

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

    ResponderEliminar
    Respuestas
    1. Aquí un ejemplo...

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

      Eliminar
  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)

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

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

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

      Eliminar
  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

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

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

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

    ResponderEliminar

Entradas Relacionadas

Related Posts Plugin for WordPress, Blogger...