En el siguiente ejemplo, el servidor será multiusuario, es decir, atenderá simultáneamente varios clientes, y para ello se utilizarán hilos -uno por cada cliente que se conecte- que atenderán en forma exclusiva el proceso de cada cliente. El cliente, por su parte, se conectará al servidor e iniciarán un diálogo (protocolo) en el cual el cliente enviará un número y el servidor devolverá el valor del área del círculo de radio igual al valor envíado por el cliente. El proceso para cada cliente terminará cuando se le envíe al servidor un valor negativo.
Servidor
El proceso del servidor inicia creando un ServerSocket para escuchar peticiones por el puerto 65432 (debe ser un valor entre 1225 y 65535 que no esté siendo utilizado en el equipo donde va a correr). Cada vez que un cliente ingrese se crea un nuevo objeto de la clase Socket y se instancia un nuevo hilo de la clase HiloServidor que se encargará de manejar la interacción con el cliente.
import java.io.*;
import java.net.*;
public class ServidorAreaCirculo {
final int puerto = 65432; // puerto sobre el que se esperarán conexiones
ServerSocket ss;
public void proceso() {
try {
ss = new ServerSocket(puerto);
while(true) { // ciclo infinito para esperar conexiones
Socket socket = ss.accept(); // espera hasta que un cliente se conecta
Thread hilo = new Thread(new HiloServidor(socket)); // crea hilo hijo
hilo.start(); // inicia el hilo hijo que atiende al cliente
}
}
catch(IOException x) {
System.err.println("Error de conexión: " + x.getMessage());
}
}
class HiloServidor implements Runnable {
Socket socket;
HiloServidor(Socket s) { socket = s; }
public void run() {
try {
// crea flujos de entrada y salida
BufferedReader in = new BufferedReader(
new InputStreamReader(socket.getInputStream()));
PrintWriter out = new PrintWriter(socket.getOutputStream());
// paso 1: envio mensaje de bienvenida
out.println("Bienvenid@, este servidor calcula áreas de círculos");
while(true) {
// paso 2: solicita envio del radio del círculo
out.println("Digite radio del circulo (ó número negativo para terminar): ");
out.flush();
// paso 3: recibe el radio y genera la salida a enviar
String cadena = in.readLine();
try {
double radio = Double.parseDouble(cadena);
if(radio<0) break;
double area = Math.PI*Math.pow(radio,2);
cadena = "El área de un círculo de radio " + radio + " es " +
String.format("%,.4f", area);
}
catch(NumberFormatException x) {
cadena = "Error, la cadena recibida no es un número válido";
}
// paso 4: devuelve el mensaje al usuario
out.println(cadena);
out.flush();
}
out.println("Gracias por venir, vuelve pronto");
out.flush();
socket.close();
}
catch(IOException x) {
System.err.println(x.getMessage());
}
}
}
public static void main(String[] args) {
ServidorAreaCirculo s = new ServidorAreaCirculo();
s.proceso();
}
}
Cliente
En este caso, el cliente inicia abriendo un socket con el equipo y puerto donde debe estar esperando el programa servidor. Para la prueba se supone que el servidor debe estar ejecutándose en la misma máquina del cliente (localhost) en el puerto 65432.
import java.io.*;
import java.io.*;
import java.net.*;
import javax.swing.*;
import static javax.swing.JOptionPane.*;
public class ClienteAreaCirculo {
public void proceso() {
try {
// Se crea socket conectado al servidor y puerto conocidos
Socket socket = new Socket("localhost",65432);
// Se crean los flujos de entrada y salida
PrintWriter out = new PrintWriter(socket.getOutputStream());
BufferedReader in = new BufferedReader(
new InputStreamReader(socket.getInputStream()));
// Paso 1: se recibe mensaje de bienvenida del servidor
String cadena = in.readLine();
System.out.println(cadena);
while(true) {
// Paso 2: se recibe mensaje de solicitud de número
cadena = in.readLine();
System.out.println(cadena);
// Paso 3: se pregunta al usuario el número a enviar
cadena = showInputDialog(cadena);
// Paso 4: se envia el número al servidor
out.println(cadena);
out.flush();
// Paso 5: se recibe la respuesta del servidor
cadena = in.readLine();
System.out.println(cadena);
if(cadena.startsWith("Gracias por venir")) break;
}
}
catch(IOException x) {
System.err.println("Error de conexión: "+x.getMessage());
}
}
public static void main(String[] args) {
ClienteAreaCirculo c = new ClienteAreaCirculo();
c.proceso();
}
}