Explicamos de forma sencilla cómo hacer dos aplicaciones Java, una cliente y otra servidor, de forma que el servidor queda a la escucha para que el cliente se conecte y le envíe un mensaje de texto. El servidor usará thread (hilos) para permitir múltiples conexiones de clientes. Usaremos como IDE de desarrollo IntelliJ IDEA, aunque el mismo código que mostramos será válido para el resto de entornos como NetBeans y Eclipse. Realizaremos pruebas reales, generando los JAR de Cliente y Servidor, para ejecutarlos en Windows y en Linux, en la red LAN y desde Internet.

Requisitos para desarrollar aplicación cliente que envíe un mensaje de texto a un servidor mediante Java

El único requisito es disponer de un IDE de desarrollo para realizar las dos aplicaciones, cliente y servidor. En nuestro caso usaremos IntelliJ IDEA 2020.2 Community, pero sirve cualquier otro como Eclipse o NetBeans. Incluso se podría desarrollar sin entorno IDE, con un bloc de notas y el compilar de java javac.

Para probar la aplicación generaremos el JAR correspondiente, que nos llevaremos a otro equipo de la red y desde este enviaremos el mensaje a otro equipo. Uno tendrá el servidor iniciado y el otro iniciará el cliente. Por lo tanto, si queremos probarlo en un entorno real necesitaremos dos equipos conectados en red. Incluso este método también funcionará a través de Internet, siempre y cuando el equipo servidor tenga una IP pública conocida y la redirección (NAT, mapeo) del puerto que se use al equipo. A continuación explicamos de forma rápida como hacer NAT de un puerto a una IP en un router estándar.

NAT/Mapeo/Redirección de puerto en router estándar de casa Livebox

Si queremos permitir que los clientes de fuera de nuestra red LAN puedan enviar mensajes al servidor, necesitaremos abrir el puerto que vayamos a usar en el router de nuestra red. Habitualmente tenemos router estándar de baja gama, explicamos cómo hacerlo en uno de estos routers, un Livebox.

En primer lugar deberemos conocer la IP del equipo que tendrá el programa servidor ejecutándose y esperando la conexión de los clientes. En nuestro caso ese equipo tiene la IP 192.168.1.10:

NAT/Mapeo/Redirección de puerto en router router estándar de casa

Deberemos conocer también la IP del router, que como vemos en la imagen anterior suele ser la puerta de enlace asignada a los equipos, la 192.168.1.1. Abriremos un navegador y accederemos a esa IP. Nos solicitará usuario y contraseña que también hemos de conocer. Una vez dentro pulsaremos en «Configuración avanzada» [1] y en «NAT/PAT» [2]:

NAT/Mapeo/Redirección de puerto en router router estándar de casa

En la parte inferior, en «Personalizar reglas», pulsaremos en el desplegable y elegiremos «Nuevo…»:

NAT/Mapeo/Redirección de puerto en router router estándar de casa

Introduciremos los datos de la regla NAT:

  • Aplicación/servicio: un nombre para la regla, por ejemplo «prueba_java».
  • Puerto interno: el puerto que usaremos para las comunicaciones entre servidor y cliente, por ejemplo 2020.
  • Puerto externo: el mismo que el anterior, 2020.
  • Protocolo: TCP.
  • IPv4 del dispositivo: en nuestro caso la IP del PC donde se ejecutará el programa Java servidor, que será la 192.168.1.10.

Una vez introducidos los datos pulsaremos «añadir» y la regla quedará habilitada y lista para usarse:

NAT/Mapeo/Redirección de puerto en router router estándar de casa

Para la conexión externa deberemos conocer, por último, la IP pública que nos ha proporcionado nuestro ISP (proveedor de Internet). Puede que sea dinámica y que vaya variando cada cierto tiempo (normalmente varios días o incluso semanas). En el propio router podemos consultarla, en Información y diagnóstico, pulsando en «Parámetros del sistema», aparecerá como «1.9 dirección IPv4»:

NAT/Mapeo/Redirección de puerto en router router estándar de casa

Aplicación Servidor que usa ServerSocket y Socket en Java y queda a la espera de recibir la conexión de los clientes y sus mensajes, con IDE IntelliJ IDEA

Abriremos IntelliJ IDEA (o el IDE de desarrollo Java que queramos) y crearemos un nuevo proyecto. En el caso de IntelliJ, es importante mencionar que según la versión del SDK de Java que usemos para compilar la aplicación, necesitaremos luego esa versión o superior de Java instalada en los equipos en los que queramos ejecutar la aplicación (sean Windows o Linux). En nuestro caso usaremos Java version 11.0.2:

Aplicación servidor que usa ServerSocket y Socket en Java y queda a la espera de recibir la conexión de los clientes y sus mensajes, con IDE IntelliJ IDEA

Marcaremos «Create project from template» y elegiremos «Command Line App». Será una aplicación de línea de comandos:

Aplicación servidor que usa ServerSocket y Socket en Java y queda a la espera de recibir la conexión de los clientes y sus mensajes, con IDE IntelliJ IDEA

Estableceremos los datos básicos para nuestro proyecto, el nombre del proyecto en «Project name», puesto que estamos creando la aplicación que hará de servidor, lo llamaremos «Servidor», la ubicación del proyecto y el paquete base, en nuestro caso com.ProyectoA:

Aplicación servidor que usa ServerSocket y Socket en Java y queda a la espera de recibir la conexión de los clientes y sus mensajes, con IDE IntelliJ IDEA

El asistente creará la clase Main por defecto. Para el caso del servidor crearemos una segunda clase, para ello pulsaremos con el botón derecho del ratón sobre la carpeta del paquete «com.ProyectoA» y en el menú emergente pulsaremos en «New» – «Java Class»:

Aplicación servidor que usa ServerSocket y Socket en Java y queda a la espera de recibir la conexión de los clientes y sus mensajes, con IDE IntelliJ IDEA

Introduciremos el nombre para la clase, por ejemplo «Servidor» y pulsaremos INTRO:

Aplicación servidor que usa ServerSocket y Socket en Java y queda a la espera de recibir la conexión de los clientes y sus mensajes, con IDE IntelliJ IDEA

El código Java para la clase Servidor.java será el siguiente. La explicación de lo que hace dicha clase viene incluida en el código:

En la clase principal Main de la aplicación Servidor, Main.java, colocaremos el siguiente código (que también viene explicado paso a paso):

Desde la clase Main instanciaremos la clase Servidor para iniciarlo y dejarlo escuchando y esperando la conexión de los clientes.

Una vez que tenemos el código Java, probaremos el Servidor pulsando en «Run ‘Main'»:

Aplicación servidor que usa ServerSocket y Socket en Java y queda a la espera de recibir la conexión de los clientes y sus mensajes, con IDE IntelliJ IDEA

El programa Servidor ser ejecutará, solicitará al usuario que introduzca el puerto (también puede pasársele por parámetro). Una vez introducido el puerto, el programa Servidor lo usará y quedará escuchando por dicho puerto las conexiones de los clientes:

Aplicación Servidor que usa ServerSocket y Socket en Java y queda a la espera de recibir la conexión de los clientes y sus mensajes, con IDE IntelliJ IDEA

El Servidor queda indefinidamente a la escucha de los clientes por el puerto indicado, hasta que algún cliente le pase el mensaje «[[fin]]», en cuyo caso se cerrará.

A continuación describimos el desarrollo de la aplicación Java Cliente.

Aplicación Cliente que usa Socket y conecta con el Servidor y envía un texto al Servidor

Procederemos de la misma forma que hemos hecho para el Servidor. Crearemos un nuevo proyecto Java con IntelliJ IDEA, que llamaremos «Cliente»:

Aplicación Cliente que usa Socket y conecta con el Servidor y envía un texto al Servidor

El Cliente, a diferencia del Servidor, solo tendrá una clase, la clase Main, que se creará por defecto al crear el proyecto. En dicha clase colocaremos el siguiente código Java:

El código del Cliente también viene explicado paso a paso en el propio código. Básicamente conectará con el servidor por la IP y puertos indicados y enviará un mensaje de texto. Admite parámetros para pasarle los tres datos (IP, puerto y mensaje) o también por consola.

El Cliente en funcionamiento, tras compilarlo, nos pedirá la dirección del Servidor, de momento, como estamos en desarrollo, tanto Cliente como Servidor se ejecutan en el mismo equipo, por lo tanto la dirección del servidor será: localhost. Nos pedirá el puerto, introduciremos el mismo en que tengamos el servidor escuchando, en nuestro caso el 2020. Y nos pedirá, por último, el mensaje de texto a enviar, lo introduciremos y pulsaremos INTRO. El mensaje se enviará al Servidor:

Aplicación Cliente que usa Socket y conecta con el Servidor y envía un texto al Servidor

Y en el Servidor, que también estaba iniciado (de lo contrario el cliente fallaría), recibirá el mensaje enviado por el Cliente:

Aplicación Cliente que usa Socket y conecta con el Servidor y envía un texto al Servidor

Podemos probar a detener el servidor para comprobar qué hará el Cliente. Si el servidor está detenido e intentamos enviar un mensaje desde un Cliente, mostrará un error:

Aplicación Cliente que usa Socket y conecta con el Servidor y envía un texto al Servidor

Como vemos, mostrará un error de conexión, Connection refused, y finalizará la aplicación Cliente con código de salida 2.

Descarga del código fuente y aplicaciones JAR completas Cliente y Servidor para enviar mensajes mediante Socket con IDE IntelliJ IDEA

A continuación os dejamos el enlace para la descarga del código fuente Java completo de estas aplicaciones (realizado con IntelliJ IDEA 2020.2):

Generar JAR con ejecutables de Cliente y Servidor para probar en equipos reales

Hasta ahora hemos probado el Cliente y el Servidor en el mismo equipo y compilándolos con IntelliJ IDEA. Ahora vamos a generar los JAR de ambos programas para ejecutarlos en real. Para generar los JAR seguiremos los pasos que explicamos en este apartado:

Generaremos el JAR de la aplicación Servidor, como indicamos en el enlace anterior, añadiendo un Artifacts:

Generar JAR con ejecutables de Cliente y Servidor para probar en equipos reales

Y generando el JAR Servidor.jar:

Generar JAR con ejecutables de Cliente y Servidor para probar en equipos reales

Y generamos el JAR para la aplicación Cliente, de la misma forma:

Generar JAR con ejecutables de Cliente y Servidor para probar en equipos reales

Y generando el JAR Cliente.jar:

Generar JAR con ejecutables de Cliente y Servidor para probar en equipos reales

En la carpeta del proyecto …\IdeaProjects\Socket_Cliente_Servidor\Cliente\out\artifacts\Cliente_jar tendremos el Cliente.jar:

Generar JAR con ejecutables de Cliente y Servidor para probar en equipos reales

Y en la carpeta del proyecto …\IdeaProjects\Socket_Cliente_Servidor\Servidor\out\artifacts\Servidor_jar tendremos el Servidor.jar:

Generar JAR con ejecutables de Cliente y Servidor para probar en equipos reales

Pruebas reales de Cliente y Servidor en equipos Windows y Linux de la misma red LAN

Realizaremos una prueba real de los programas Cliente y Servidor. Por ejemplo, ejecuaremos el programa Servidor, a la escucha por el puerto 2020, en un equipo con Windows 10. Y ejecutaremos el programa Cliente, en otro equipo con Linux y otro equipo con Windows.

Iniciaremos el programa Servidor (Servidor.jar) en el equipo con Windows 10, para ello abriremos una ventana de MS-DOS (de línea de comandos o cmd) y accederemos a la carpeta donde tengamos el programa Servidor.jar, por ejemplo a «Servidor_Java_ProyectoA», con el comando:

cd C:\Servidor_Java_Proyecto_A

A continuación ejecutaremos el siguiente comando Java para iniciar el .jar:

java -jar Servidor.jar

Si tenemos la versión correcta de Java y está agregada a la variable de entorno PATH se iniciará la aplicación Servidor y nos solicitará un puerto donde escuchar, introduciremos, por ejemplo, 2020 y pulsaremos INTRO. Si todo es correcto el Servidor permanecerá en escucha, esperando la conexión de los clientes:

Pruebas reales de Cliente y Servidor en equipos Windows y Linux de la misma red LAN

Si se produce algún error en el comando java -jar, se pueden seguir los pasos de estos manuales (Windows y Linus) para configurar correctamente Java para la ejecución de aplicaciones .jar:

El Servidor tiene la IP 192.168.1.10, se puede consultar desde la línea de comandos con el comando ipconfig:

Pruebas reales de Cliente y Servidor en equipos Windows y Linux de la misma red LAN

Necesitaremos este dato para poder conectar los clientes.

Una vez que el Servidor queda a la escucha, ahora iniciaremos un cliente, por ejemplo un equipo Linux, de la misma red LAN que el servidor. Deberemos copiar el fichero Cliente.jar al equipo Linux, por ejemplo pasándolo con Filezilla desde el equipo Windows (o de cualquier otra forma):

Pruebas reales de Cliente y Servidor en equipos Windows y Linux de la misma red LAN

Una vez pasado el fichero Cliente.jar, desde el equipo Linux, desde una ventana de terminal, accederemos a la carpeta del jar (igual que en el caso de Windows). En nuestro caso hemos colocado el fichero Cliente.jar en la carpeta /tmp, por lo tanto:

cd /tmp

A continuación ejecutaremos el fichero Cliente.jar igual que hemos hecho con el fichero Servidor.jar en Windows:

java -jar Cliente.jar

Si tenemos la máquina virtual Java y tenemos las versiones correctas (como explicamos en este artículo) se iniciará el cliente y nos pedirá los siguientes datos:

  • Dirección IP del servidor: como hemos obtenido anteriormente, en nuestro caso, la 192.168.1.10.
  • Puerto: en todo el artículo estamos usando siempre el 2020.
  • Mensaje: introduciremos el mensaje de texto que se enviará al servidor. Por ejemplo «Prueba envío mensaje desde Linux».

Tras pulsar INTRO en el mensaje el Cliente conectará con el Servidor y enviará el mensaje:

Pruebas reales de Cliente y Servidor en equipos Windows y Linux de la misma red LAN

Comprobaremos en el Servidor que el mensaje ha llegado correctamente:

Pruebas reales de Cliente y Servidor en equipos Windows y Linux de la misma red LAN

Vemos que sí, que desde el cliente con IP 192.168.1.5 (el cliente Linux) ha llegado el mensaje correctamente.

Ahora probaremos también la aplicación con un cliente Windows. Procederemos de la misma forma, copiando el fichero Cliente.jar, abriendo una ventana de MS-DOS (cmd) y ejecutándolo igual que en Linux, con el comando:

java -jar Cliente.jar

Si todo es correcto se iniciará el Cliente y nos solicitará los mismos datos que en el caso del Cliente Linux. Enviaremos el mensaje al Servidor:

Pruebas reales de Cliente y Servidor en equipos Windows y Linux de la misma red LAN

Y comprobaremos que ha llegado al Servidor:

Pruebas reales de Cliente y Servidor en equipos Windows y Linux de la misma red LAN

Vemos que ha llegado, desde la IP 192.168.1.12, que es la IP del equipo Windows Cliente. También vemos que la tilde de «envío» no ha llegado correctamente. En realidad sí que ha llegado, solo que en las consolas de MS-DOS (símbolo de sistema o cmd) de Windows hay que indicar, con el siguiente comando, el tipo de codificación. En el Cliente escribiremos el siguiente comando antes de conectar con el Servidor:

chcp 1252

Nos devolverá el mensaje «Página de códigos activa: 1252».

Ahora realizaremos la conexión y enviaremos un mensaje, veremos que las tildes (acentos) y las eñes y demás caracteres se envían:

Pruebas reales de Cliente y Servidor en equipos Windows y Linux de la misma red LAN

Y también llegan al servidor correctamente:

Pruebas reales de Cliente y Servidor en equipos Windows y Linux de la misma red LAN

Y como vemos en la última imagen, el servidor siempre permanece escuchando y atendiendo a los clientes, salvo que se le envíe el mensaje «[[fin]]» en cuyo caso finalizará. Antes de cerrarlo, haremos una última prueba real, enviando un mensaje desde un PC de Internet, de fuera de nuestra red LAN, como explicamos a continuación.

Enviar mensaje desde Cliente que está fuera de la red LAN, desde Internet, a Servidor

En los ejemplos reales anteriores todos los clientes estaban en la misma red que el Servidor. Ahora vamos a conectar con el Servidor desde un cliente de fuera de la red. Para ello debemos seguir estos pasos que indicamos al principio del artículo, para redireccionar el puerto 2020 (en nuestro caso) a la IP del Servidor (192.168.1.10 en nuestro caso).

Deberemos conocer la IP pública que nos proporciona el ISP (proveedor de Intenet) de donde tenemos el Servidor, como también explicamos aquí.

Pasaremos el fichero Cliente.jar al equipo de Internet, por el medio que sea. Ejecutaremos el Cliente.jar de la misma forma que hemos explicado anteriormente (sea Windows o Linux). En este caso, en la dirección IP del servidor introcudremos la IP pública obtenida anteriormente, en nuestro caso 5.19.6.174:

Enviar mensaje desde Cliente que está fuera de la red LAN, desde Internet, a Servidor

Comprobaremos que ha llegado el mensaje del Cliente de Internet al Servidor:

Enviar mensaje desde Cliente que está fuera de la red LAN, desde Internet, a Servidor

Vemos que el Cliente, con IP pública 7.4.1.10 ha enviado el mensaje correctamente al Servidor.

Ahora podremos detener el Servidor enviado el mensaje [[fin]] desde un Cliente:

Enviar mensaje desde Cliente que está fuera de la red LAN, desde Internet, a Servidor