Conexión de múltiples clientes. Hilos
Un
único servidor con la clase ServerSocket
e invocar al método accept() para
esperar las peticiones de conexión de los clientes.
Cuando
un cliente se conecta, el método accept()
devuelve un objeto Socket, éste se
usará para crear un hilo cuya misión es atender a este cliente.
Después
se vuelve a invocar a accept() para
esperar a un nuevo cliente; habitualmente la espera de conexiones se hace
dentro de un bucle infinito.
Archivo Servidor.java
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class Servidor {
public static void main(String args[]) throws IOException {
ServerSocket servidor;
servidor = new
ServerSocket(6000);
System.out.println("Servidor
iniciado...");
while (true) {
Socket cliente = new Socket();
cliente=servidor.accept();//esperando
cliente
HiloServidor
hilo = new HiloServidor(cliente);
hilo.start(); //Se atiende
al cliente
}// Fin de
while
}// Fin de
main
}// Fin de Servidor
Clases para Sockets UDP
Los
Sockets UDP son más simples y eficientes que los TCP pero no está garantizada
la entrega de paquetes.
No es
necesario establecer una “conexión” entre cliente y servidor, como en el caso
de TCP.
Los
datagramas deben contener explícitamente la dirección IP y el puerto de
destino.
El
paquete del datagrama está formado por los siguientes campos:
Clase DatagramPacket
Crea
instancias de los paquetes Datagrama.
Constructores
Algunos métodos importantes
Clase DatagramSocket
Da
soporte a sockets para el envío y recepción de datagramas UDP.
Constructores
Algunos métodos importantes son
Gestión de sockets UDP
En los
sockets UDP no se establece conexión.
Podemos
considerar servidor al que espera un mensaje y responde; y cliente al que
inicia la comunicación.
Tanto
uno como otro si desean ponerse en contacto necesitan saber en qué ordenador y
en qué puerto está escuchando el otro.
- El servidor crea un socket asociado a un puerto local para escuchar peticiones de clientes. Permanece a la espera de recibir peticiones.
- El cliente creará un socket para comunicarse con el servidor. Para enviar datagramas necesita conocer su IP y el puerto por el que escucha. Utilizará el método send() del socket para enviar la petición en forma de datagrama.
- El servidor recibe las peticiones mediante el método receive() del socket. En el datagrama va incluido además del mensaje, el puerto y la IP del cliente emisor de la petición; lo que le permite al servidor conocer la dirección del emisor del datagrama. Utilizando el método send() del socket puede enviar la respuesta al cliente emisor.
- El cliente recibe la respuesta del servidor mediante el método receive() del socket.
- El servidor permanece a la espera de recibir más peticiones.
Ejemplo
Archivo ServidorUDP.java
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
public class ServidorUDP {
public static void main(String[] argv) throws Exception {
byte[] bufer = new byte[1024];//bufer
para recibir el datagrama
//ASOCIO EL
SOCKET AL PUERTO 12345
DatagramSocket socket = new
DatagramSocket(12345);
//ESPERANDO
DATAGRAMA
System.out.println("Esperando
Datagrama ................");
DatagramPacket recibo = new DatagramPacket(bufer, bufer.length);
socket.receive(recibo);//recibo
datagrama
int bytesRec = recibo.getLength();//obtengo
numero de bytes
String paquete= new String(recibo.getData());//obtengo
String
//VISUALIZO
INFORMACIÓN
System.out.println("Número
de Bytes recibidos: " + bytesRec);
System.out.println("Contenido
del Paquete : " + paquete.trim());
System.out.println("Puerto
origen del mensaje: " + recibo.getPort());
System.out.println("IP de
origen : " + recibo.getAddress().getHostAddress());
System.out.println("Puerto
destino del mensaje:" + socket.getLocalPort());
socket.close(); //cierro
el socket
}//Fin de
main
}// Fin de SerivdorUDP
El
programa servidor (ServidorUDP) recibe un datagrama enviado por un programa
cliente. El programa servidor permanece
a la espera hasta que le llega un paquete del cliente; en este momento
visualiza: el número de bytes recibidos, el contenido del paquete, el puerto y
la IP del programa cliente y el puerto local por el que recibe las peticiones.
Archivo ClienteUDP.java
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
public class ClienteUDP {
public static void main(String[] argv) throws Exception {
InetAddress destino = InetAddress.getLocalHost();
int port = 12345; //puerto
al que envío el datagrama
byte[] mensaje = new byte[1024];
String Saludo="Enviando
Saludos !!";
mensaje = Saludo.getBytes(); //codifico
String a bytes
//CONSTRUYO EL
DATAGRAMA A ENVIAR
DatagramPacket envio = new DatagramPacket
(mensaje, mensaje.length, destino, port);
DatagramSocket socket = new
DatagramSocket(34567);//Puerto local
System.out.println("Enviando
Datagrama de longitud: "+ mensaje.length);
System.out.println("Host
destino : "+ destino.getHostName());
System.out.println("IP
Destino : " + destino.getHostAddress());
System.out.println("Puerto
local del socket: " + socket.getLocalPort());
System.out.println("Puerto
al que envio: " + envio.getPort());
//ENVIO
DATAGRAMA
socket.send(envio);
socket.close(); //cierro
el socket
}//Fin de
main
}//Fin de ClienteUDP
El
programa cliente envía un mensaje al servidor (máquina destino, en este caso es
la máquina local, localhost) al puero 12345 por el que espera peticiones.
Visualiza el nombre del host de destino y la dirección IP. También visualiza el
puerto local del socket y el puerto al que envía el mensaje.
Ejemplo 2
Archivo ClienteUDP2.java
import java.io.*;
import java.net.*;
public class ClienteUDP2 {
public static void main(String args[]) throws Exception {
// FLUJO PARA
ENTRADA ESTANDAR
BufferedReader in = new BufferedReader
(new
InputStreamReader(System.in));
DatagramSocket clientSocket = new
DatagramSocket();//socket cliente
byte[] enviados = new byte[1024];
byte[] recibidos = new byte[1024];
// DATOS DEL
SERVIDOR al que enviar mensaje
InetAddress IPServidor = InetAddress.getLocalHost();// localhost
int puerto = 9876; // puerto
por el que escucha
// INTRODUCIR
DATOS POR TECLADO
System.out.print("Introduce
mensaje: ");
String cadena = in.readLine();
enviados = cadena.getBytes();
// ENVIANDO
DATAGRAMA AL SERVIDOR
System.out.println("Enviando
" + enviados.length + " bytes al servidor.");
DatagramPacket envio = new DatagramPacket
(enviados, enviados.length, IPServidor, puerto);
clientSocket.send(envio);
// RECIBIENDO
DATAGRAMÄ DEL SERVIDOR
DatagramPacket recibo = new DatagramPacket
(recibidos, recibidos.length);
System.out.println("Esperando
datagrama....");
clientSocket.receive(recibo);
String mayuscula = new String(recibo.getData());
// OBTENIDENDO
INFORMACIÓN DEL DATAGRAMA
InetAddress IPOrigen = recibo.getAddress();
int puertoOrigen = recibo.getPort();
System.out.println("\tProcedente
de: " + IPOrigen + ":" + puertoOrigen);
System.out.println("\tDatos:
" + mayuscula.trim());
//cerrar
socket
clientSocket.close();
}//Fin de
main
}//Fin de ClienteUDP2
El
programa cliente envía un texto tecleado en su entrada estándar al servidor (en
un pueto pactado), el servidor lee el datagrama y devuelve al cliente el texto
en mayúscula. El programa cliente recibe un datagrama del servidor y muestra
información del mismo en pantalla (IP, puerto del servidor y el texto en
mayúscula).
Archivo ServidorUDP2.java
import java.io.*;
import java.net.*;
public class ServidorUDP2 {
public static void main(String args[]) throws Exception {
//Puerto
por el que escucha el servidor: 9876
DatagramSocket serverSocket = new
DatagramSocket(9876);
byte[] recibidos = new byte[1024];
byte[] enviados = new byte[1024];
String cadena;
while(true) {
System.out.println ("Esperando
datagrama.....");
//RECIBO
DATAGRAMA
recibidos = new byte[1024];
DatagramPacket
paqRecibido = new DatagramPacket
(recibidos, recibidos.length);
serverSocket.receive(paqRecibido);
cadena = new String(paqRecibido.getData());
//DIRECCION
ORIGEN
InetAddress
IPOrigen = paqRecibido.getAddress();
int puerto = paqRecibido.getPort();
System.out.println ("\tOrigen:
" + IPOrigen + ":" + puerto);
System.out.println ("\tMensaje
recibido: " + cadena.trim());
//CONVERTIR
CADENA A MAYÚSCULA
String mayuscula = cadena.trim().toUpperCase();
enviados = mayuscula.getBytes();
//ENVIO
DATAGRAMA AL CLIENTE
DatagramPacket
paqEnviado = new DatagramPacket
(enviados, enviados.length, IPOrigen, puerto);
serverSocket.send(paqEnviado);
//Para terminar
if(cadena.trim().equals("*")) break;
}//Fin de
while
serverSocket.close();
System.out.println ("Socket
cerrado...");
}//Fin de
main
}//Fin de ServidorUDP2
El
programa servidor finaliza cuando recibe como cadena un asterisco.
MulticastSocket
La
clase MulticastSocket es útil para
enviar paquetes a múltiples destinos simultáneamente.
Para
poder recibir estos paquetes es necesario establecer un grupo multicast, que es
un grupo de direcciones IP que comparten el mismo número de puerto.
Cuando
se envía un mensaje a un grupo de multicast, todos los que pertenezcan a ese
grupo recibirán el mensaje.
La
pertenencia al grupo es transparente al emisor, es decir, el emisor no conoce
el número de miembros del grupo ni sus direcciones IP.
Grupo multicast
Un
grupo multicast sse especifica mediante una dirección IP de clase D y un número
de puerto UDP estándar.
Las
direcciones desde la 224.0.0.0 a la 239.255.255.255 están destinadas para ser
direcciones de multicast.
La
dirección 224.0.0.0 está reservada y no debe ser utilizada.
Constructores
Algunos métodos importantes son
Esquema general para un servidor
multicast:
- Se crea el socket multicast. No hace falta especificar puerto
MuslticastSocket ms = new MulticastSocket();
- Se define el pueto multicast
int Puerto = 12345;
- Se crea el grupo multicast
InetAddress grupo =
InetAddress.getByName(“225.0.0.1”);
- Se crea el datagrama
DatagramPacket paquete = new
DatagramPacket(msg.getBytes(), msg.length(), grupo, Puerto);
- Se envía el paquete al grupo
ms.send(paquete);
- Se cierra el socket
ms.close();
Esquema general para un cliente
multicast:
- Se crea un socket multicast en el puerto establecido
MulticastSocket ms = new
MulticastSocket(12345);
- Se configura la IP del grupo al que nos conectaremos
InetAddress grupo =
InetAddress.getByName(“225.0.0.1”);
- Se une al grupo
ms.joinGroup(grupo);
- Recibe el paquete del servidor multicast
byte[] buf = new byte[1000];
DatagramPacket recibido = new
DatagramPacket(buf, buf.length);
ms.receive(recibido);
- Salimos del grupo multicast:
ms.leaveGroup(grupo);
- Se cierra el socket
ms.close();
Ejemplo
En este
ejemplo tenemos un servidor multicast que lee datos por teclado y los envía a
todos los clientes que pertenezcan al grupo multicast, el proceso terminará
cuando se introduzca un asterisco.
El programa
cliente visualiza el paquete que recibe el servidor, su proceso finaliza cuando
recibe un asterisco.
Archivo ServidorMC.java
import java.io.*;
import java.net.*;
public class ServidorMC {
public static void main(String args[]) throws Exception {
// FLUJO PARA
ENTRADA ESTANDAR
BufferedReader in = new BufferedReader(new
InputStreamReader(System.in));
//Se crea
el socket multicast.
MulticastSocket ms = new
MulticastSocket();
int Puerto = 12345;//Puerto
multicast
InetAddress grupo = InetAddress.getByName("225.0.0.1");//Grupo
String cadena="";
while(!cadena.trim().equals("*")) {
System.out.print("Datos a
enviar al grupo: ");
cadena = in.readLine();
// ENVIANDO AL
GRUPO
DatagramPacket
paquete = new DatagramPacket
(cadena.getBytes(), cadena.length(), grupo, Puerto);
ms.send (paquete);
}//Fin de
while
//cierro
socket
ms.close ();
System.out.println ("Socket
cerrado...");
}//Fin de
main
}//Fin de ServidorMC
Archivo ClienteMC.java
import java.io.*;
import java.net.*;
public class ClienteMC {
public static void main(String args[]) throws Exception {
//Se crea
el socket multicast
int Puerto = 12345;//Puerto
multicast
MulticastSocket ms = new
MulticastSocket(Puerto);
InetAddress grupo = InetAddress.getByName("225.0.0.1");//Grupo
//Nos unimos
al grupo
ms.joinGroup (grupo);
String msg="";
while(!msg.trim().equals("*")) {
//Recibe
el paquete del servidor multicast
byte[] buf = new byte[1000]; // Genero
dentro el buffer para que se sobreescriba al
enviar un nuevo mensaje
DatagramPacket
paquete = new DatagramPacket(buf, buf.length);
ms.receive(paquete);
msg = new String(paquete.getData());
System.out.println ("Recibo:
" + msg.trim());
}//Fin de
while
ms.leaveGroup(grupo); //abandonamos
grupo
//cierra
socket
ms.close();
System.out.println("Socket
cerrado...");
}//Fin de
main
}//Fin de ClienteMC
El HiloServidor de donde lo sacas?
ResponderEliminar