Clase Socket de Java
Socket es el bloque de construcción básico de la comunicación en red; permite el intercambio de datos entre diferentes computadoras a través de la red.
En Java,java.net.Socketla clase proporciona la funcionalidad de cliente para implementar la comunicación en red.
Puedes imaginar Socket como una conexión entre dos teléfonos:
- Un extremo es el cliente (la persona que llama)
- El otro extremo es el servidor (la persona que contesta)
- Una vez establecida la conexión, ambas partes pueden enviarse y recibir información mutuamente.
Uso básico de la clase Socket
Crear una conexión Socket
Para crear una conexión Socket, necesitas especificar la dirección y el puerto del servidor:
Ejemplo
try {
// Conectar al puerto 8080 de localhost
Socket socket = new Socket("localhost", 8080);
// Usar el socket para comunicarse...
// Cerrar la conexión
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
// Conectar al puerto 8080 de localhost
Socket socket = new Socket("localhost", 8080);
// Usar el socket para comunicarse...
// Cerrar la conexión
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
Métodos principales
La clase Socket proporciona varios métodos importantes:
| Método | Descripción |
|---|---|
getInputStream() |
Obtiene el flujo de entrada para recibir datos. |
getOutputStream() |
Obtiene el flujo de salida para enviar datos. |
close() |
Cierra la conexión Socket. |
isConnected() |
Verifica si la conexión está establecida. |
setSoTimeout(int timeout) |
Establece el tiempo de espera (milisegundos). |
Implementar comunicación cliente-servidor
Ejemplo de cliente
Ejemplo
import java.io.*;
import java.net.*;
public class Client {
public static void main(String[] args) {
try {
// 1. Crear la conexión Socket
Socket socket = new Socket("localhost", 12345);
// 2. Obtener el flujo de salida, enviar datos al servidor
PrintWriter out = new PrintWriter(
socket.getOutputStream(), true);
out.println("Hello Server!");
// 3. Obtener el flujo de entrada, recibir la respuesta del servidor
BufferedReader in = new BufferedReader(
new InputStreamReader(socket.getInputStream()));
String response = in.readLine();
System.out.println("Server response: " + response);
// 4. Cerrar la conexión
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
import java.net.*;
public class Client {
public static void main(String[] args) {
try {
// 1. Crear la conexión Socket
Socket socket = new Socket("localhost", 12345);
// 2. Obtener el flujo de salida, enviar datos al servidor
PrintWriter out = new PrintWriter(
socket.getOutputStream(), true);
out.println("Hello Server!");
// 3. Obtener el flujo de entrada, recibir la respuesta del servidor
BufferedReader in = new BufferedReader(
new InputStreamReader(socket.getInputStream()));
String response = in.readLine();
System.out.println("Server response: " + response);
// 4. Cerrar la conexión
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Ejemplo de servidor
El lado del servidor necesita usarServerSocketla clase:
Ejemplo
import java.io.*;
import java.net.*;
public class Server {
public static void main(String[] args) {
try {
// 1. Crear ServerSocket, escuchando en el puerto especificado
ServerSocket serverSocket = new ServerSocket(12345);
System.out.println("Server started. Waiting for client...");
// 2. Esperar la conexión del cliente
Socket clientSocket = serverSocket.accept();
System.out.println("Client connected.");
// 3. Obtener el flujo de entrada, leer el mensaje del cliente
BufferedReader in = new BufferedReader(
new InputStreamReader(clientSocket.getInputStream()));
String message = in.readLine();
System.out.println("Client says: " + message);
// 4. Obtener el flujo de salida, enviar la respuesta al cliente
PrintWriter out = new PrintWriter(
clientSocket.getOutputStream(), true);
out.println("Hello Client!");
// 5. Cerrar la conexión
clientSocket.close();
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
import java.net.*;
public class Server {
public static void main(String[] args) {
try {
// 1. Crear ServerSocket, escuchando en el puerto especificado
ServerSocket serverSocket = new ServerSocket(12345);
System.out.println("Server started. Waiting for client...");
// 2. Esperar la conexión del cliente
Socket clientSocket = serverSocket.accept();
System.out.println("Client connected.");
// 3. Obtener el flujo de entrada, leer el mensaje del cliente
BufferedReader in = new BufferedReader(
new InputStreamReader(clientSocket.getInputStream()));
String message = in.readLine();
System.out.println("Client says: " + message);
// 4. Obtener el flujo de salida, enviar la respuesta al cliente
PrintWriter out = new PrintWriter(
clientSocket.getOutputStream(), true);
out.println("Hello Client!");
// 5. Cerrar la conexión
clientSocket.close();
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Características avanzadas de Socket
Establecer tiempo de espera (timeout)
Ejemplo
Socket socket = new Socket();
// Establecer el tiempo de espera de conexión a 5 segundos
socket.connect(new InetSocketAddress("example.com", 80), 5000);
// Establecer el tiempo de espera de lectura a 3 segundos
socket.setSoTimeout(3000);
// Establecer el tiempo de espera de conexión a 5 segundos
socket.connect(new InetSocketAddress("example.com", 80), 5000);
// Establecer el tiempo de espera de lectura a 3 segundos
socket.setSoTimeout(3000);
Mantener la conexión
Ejemplo
// Habilitar el mecanismo TCP keep-alive
socket.setKeepAlive(true);
socket.setKeepAlive(true);
Tamaño del búfer
Ejemplo
// Establecer el tamaño del búfer de recepción (bytes)
socket.setReceiveBufferSize(8192);
// Establecer el tamaño del búfer de envío (bytes)
socket.setSendBufferSize(8192);
socket.setReceiveBufferSize(8192);
// Establecer el tamaño del búfer de envío (bytes)
socket.setSendBufferSize(8192);
Problemas comunes y soluciones
Conexión rechazada
- Verificar si el servidor se está ejecutando
- Confirmar que el número de puerto sea correcto
- Verificar la configuración del firewall
Tiempo de espera de conexión agotado
- Verificar la conexión de red
- Aumentar el tiempo de espera
- Confirmar que la dirección del servidor sea correcta
Recepción de datos incompleta
- Asegurarse de que ambas partes usen el mismo protocolo
- Verificar que el tamaño del búfer sea suficiente
- Considerar el uso de delimitadores o mensajes de longitud fija
Escenarios de aplicación práctica
La programación con Socket tiene amplias aplicaciones en la práctica:
- Aplicaciones de mensajería instantánea (como WeChat, QQ)
- Juegos en línea
- Software de control remoto
- Herramientas de transferencia de archivos
- Comunicación de dispositivos IoT (Internet de las cosas)
Mejores prácticas
- Manejar siempre las excepciones de E/S
- Usar try-with-resources para asegurar la liberación de recursos
- Establecer tiempos de espera razonables para operaciones importantes
- Considerar el uso de un pool de hilos para manejar múltiples conexiones
- Diseñar un protocolo de comunicación claro