Tema 3:
Interfaz de programación
en red: Los Sockets
Bibliografía:
● Kurose04, Apartados 2.1, 2.6, 2.7 y 2.8
● “El lenguaje de programación Java”, V. Alonso, M. Sánchez,
Redes: Tema 3 SPUPV-2003. Libro-Apunte nº 922, Capítulos 5, 6 y 7 1
Objetivos
Conocer:
● Qué interfaz ofrecen los sistemas operativos para
acceder a los servicios de red
● Cuál es la estructura básica de un cliente
● Cuál es la estructura básica de un servidor
● Cómo gestionar simultáneamente varios clientes
Redes: Tema 3 2
Índice
1. El modelo cliente-servidor
2. La abstracción de los sockets
3. Los sockets en Java
4. Sockets TCP
5. Sockets UDP
6. Servidores concurrentes
7. Ejemplos
Redes: Tema 3 3
1. El Modelo Cliente-Servidor
● Arquitectura de las aplicaciones en red
●
Cliente-servidor
● Los papeles de cada computador están claramente
diferenciados:
– Uno hace de cliente y el otro de servidor
●
Entre pares (P2P)
● Los computadores alternan el papel de cliente y de
servidor
● Sin embargo, para una transferencia determinada,
uno hace de cliente y el otro de servidor
Redes: Tema 3 4
Modelo Cliente-Servidor
Cuando dos procesos se comunican, siguen un
modelo cliente y servidor
1. Petición
cliente Internet servidor
2. Respuesta
Cliente: Servidor:
● Inicia la comunicación ● Espera peticiones
● Solicita un servicio al servidor ● Proporciona el servicio solicitado
● Ejemplo:
● Ejemplo:
● Un cliente web solicita una página
● El servidor web envía la página
solicitada por el cliente
● Un proceso P2P solicita un fichero a
otro proceso P2P
● El proceso P2P envía el fichero
solicitado por otro proceso P2P
Redes: Tema 3 5
Modelo cliente-servidor
● Los dos extremos dialogan siguiendo un protocolo
de aplicación
cliente Internet servidor
GET / HTTP/1.0
HTTP/1.0 200 OK
Content-type: text/html
<html> .... </html>
● Los RFC (Request For Comments) documentan los
protocolos de aplicación estándar
http://www.rfc-editor.org
Redes: Tema 3 6
Tipos de servidores
● Normalmente, un servidor debe estar preparado
para atender muchos clientes
● Se puede hacer de dos maneras:
● Secuencial: un cliente detrás de otro
● Concurrente: varios clientes al mismo tiempo
Redes: Tema 3 7
2. La abstracción de los sockets
● Clientes y servidores utilizan protocolos de transporte
Los procesos de las HTTP POP3
aplicaciones residen en
el espacio de usuario FTP DNS
API
Los procesos de los TCP UDP
protocolos de Red
transporte forman Enlace de datos
parte del S.O.
Físico
● Se necesita un mecanismo para ponerlos en contacto
● API (Application Programming Interface)
Redes: Tema 3 8
API socket
● Originalmente diseñado en BSD Unix
● Permite a las aplicaciones utilizar los protocolos de la
pila TCP/IP
● Define las operaciones HTTP POP3
permitidas y sus
argumentos FTP DNS
● Parecido a la forma de socket socket socket socket
acceder a los ficheros en Unix TCP UDP
● Operaciones: open, read, Red
write, close Enlace de datos
● Cuando se abre un fichero Físico
obtenemos un descriptor
● Es un estándar de facto
Redes: Tema 3 9
Socket
● Es una abstracción del sistema operativo (no Hw)
● Las aplicaciones los crean, los utilizan y los cierran cuando
ya no son necesarios
● Su funcionamiento está controlado por el sistema operativo
● Comunicación entre procesos
● Los procesos envían/reciben mensajes a través de su socket
● Los socket se comunican entre ellos
proceso proceso
socket socket
Transporte Transporte
Red Red
Enlace Enlace
Físico Internet Físico
Redes: Tema 3 10
Identificación de los sockets
● La comunicación en Internet es de socket a socket
● El proceso que está comunicándose se identifica por
medio de su socket
● El socket tiene un identificador
Identificador = dir. IP del computador + núm. puerto
cliente servidor IP:62.3.3.3
IP:128.1.1.1
socket socket
Puerto: 1245 Transporte Puerto: 80
Transporte
Red Red
Enlace Enlace
Físico Internet Físico
Redes: Tema 3 11
Tipos de sockets
●
Sockets TCP ● Sockets UDP
● Las aplicaciones piden al ● Las aplicaciones piden al
S.O. una comunicación S.O. una comunicación
controlada por TCP: controlada por UDP:
● Transferencia de bloques
● Orientada a la conexión
de datos
● Comunicación fiable y ● Sin conexión ni fiabilidad ni
ordenada entrega ordenada
Permite difusiones
También se denominan
●
●
sockets de tipo Stream
● También se denominan
sockets de tipo Datagrama
cliente servidor cliente servidor
socket socket socket socket
TCP TCP UDP UDP
bytes datagramas
Redes: Tema 3 12
3. Los sockets en Java
●
Dentro del paquete java.net existen tres clases de
sockets:
●
Socket Cliente TCP
● ServerSocket Servidor TCP
● DatagramSocket Cliente/Servidor UDP
● También hay otras clases auxiliares que facilitan la
programación de aplicaciones en red
http://java.sun.com/j2se/1.4.2/docs/api/index.html
Redes: Tema 3 13
Direcciones IP en Java
Clase InetAddress
●
InetAddress es la clase que se utiliza para
almacenar direcciones IP
● Algunos métodos
● InetAddress getByName(String nombre)
● Obtiene la dirección IP asociada a un nombre
● String getHostAddress()
● Devuelve la dirección IP en formato "aa.bb.cc.dd"
● String getHostName()
● Devuelve el nombre del host
Redes: Tema 3 14
4. Sockets TCP
● Cliente: ● Cuando un cliente se
● Inicia la conexión con el conecta con un servidor:
servidor ● El servidor crea un nuevo socket
● Especifica la dirección IP y el (2) para que el proceso servidor
puerto del proceso servidor se comunique con el cliente
● Cuando crea un socket ● De esta forma es posible que un
establece la conexión con el
servidor se comunique con
servidor
varios clientes simultáneamente
● Servidor:
● Ha de estar en ejecución
● Debe haber creado un socket
(1) donde recibir a los clientes socket
que conectan con él 1
● Espera a que algún cliente se cliente servidor
conecte
socket socket
cliente 2
bytes
Redes: Tema 3 15
Gestión de los flujos de entrada
● InputStream proporciona un flujo de bytes
● Se puede leer un byte: read()
● O un grupo de bytes: read(byte[] b)
● InputStreamReader convierte un flujo de bytes en un
flujo de caracteres
● Se puede leer un carácter: read()
● O un grupo de caracteres: read(char[] text)
● BufferedReader añade un buffer al flujo
caracteres buffer strings
● Se puede leer una línea de texto: String readLine()
Redes: Tema 3 16
Gestión de los flujos de salida
● OutputStream admite un flujo de bytes
● Se puede escribir un byte: write(int b)
● O un grupo de bytes: write(byte[] b)
● PrintWriter permite enviar texto (caracteres)
● Tiene métodos que permiten escribir una línea de texto:
print(String s) y println(String s)
líneas bytes
Redes: Tema 3 17
Clientes TCP
Clase Socket
● Constructores
● Socket(InetAdress dirIP, int puerto)
● Socket(String nombre, int puerto)
● Crea un socket y lo conecta con el servidor indicado
● Socket(InetAddress dirIP, int puerto,
InetAddress dirIPLocal, int puertoLocal)
● Socket(String nombre, int puerto,
InetAddress dirIPLocal, int puertoLocal)
● Crea un socket y lo conecta con el servidor indicado,
ligándolo a una dirección IP y puerto locales concretos
Redes: Tema 3 18
Clientes TCP
Clase Socket
● Algunos métodos importantes
● InputStream getInputStream()
● Proporciona un descriptor para leer del socket
● OutputStream getOutputStream()
● Proporciona un descriptor para escribir en el socket
● close()
● Cierra el socket
Redes: Tema 3 19
Cliente TCP básico
import java.net.*;
import java.io.*;
class ClienteTCP {
public static void main(String args[])
throws UnknownHostException, IOException {
Socket s=new Socket("zoltar.redes.upv.es",21);
BufferedReader in=new BufferedReader(new
InputStreamReader(s.getInputStream()));
System.out.println(in.readLine());
s.close();
}
● Este cliente se conecta al servidor FTP (puerto 21) y
visualiza la primera línea que recibe del servidor. Después
cierra la conexión
● Genera la siguiente salida:
220 (vsFTPd 1.2.1)
Redes: Tema 3 20
Segundo cliente TCP
import java.net.*;
import java.io.*;
class ClienteTCP2 {
public static void main(String args[]) throws UnknownHostException,IOException {
Socket s = new Socket("www.upv.es",80);
BufferedReader in =
new BufferedReader(new InputStreamReader(s.getInputStream()));
PrintWriter out = new PrintWriter(s.getOutputStream());
out.print("GET / HTTP/1.0" + "\r\n");
out.print("\r\n");
out.flush();
System.out.println(in.readLine());
s.close();
}
● Envía una petición HTTP al servidor www.upv.es
● Esta es la salida del programa:
HTTP/1.1 200 OK
Redes: Tema 3 21
Servidores TCP
Clase ServerSocket
● Constructores
● ServerSocket(int puerto)
● Abre un socket en el puerto indicado en modo de escucha
● Si port = 0, entonces se elige cualquier puerto libre
● ServerSocket(int puerto, int backlog)
● Abre un socket en el puerto indicado en modo de escucha
● backlog indica la longitud máxima de la cola de
conexiones en espera
● Cuando llega una solicitud de conexión y la cola está
llena, se rechaza la conexión
Redes: Tema 3 22
Servidores TCP
Clase ServerSocket
● Algunos métodos importantes
● Socket accept()
● Acepta una conexión de un cliente y devuelve un socket
asociado a ella
● El proceso se bloquea hasta que se realiza una conexión
● El diálogo con el cliente se hace por el nuevo socket
● El ServerSocket puede atender nuevas conexiones
● close()
● Cierra el socket servidor
Redes: Tema 3 23
Primer servidor TCP
import java.net.*;
import java.io.*;
class ServidorTCP {
public static void main(String args[]) throws UnknownHostException,IOException {
ServerSocket ss=new ServerSocket(7777);
Socket s=ss.accept(); // espero a que llegue un cliente
PrintWriter out=new PrintWriter(s.getOutputStream(),true);
out.println("Bienvenido al servidor de prueba de Redes");
s.close();
ss.close();
}
}
● El servidor espera un cliente. Cuando éste se conecta, el
servidor le envía una cadena de bienvenida y acaba
zoltar:~/java> telnet localhost 7777
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Bienvenido al servidor de prueba de Redes
Connection closed by foreign host.
Redes: Tema 3 24
Segundo servidor TCP
import java.net.*;
import java.io.*;
class ServidorTCP2 {
public static void main(String args[]) throws UnknownHostException,IOException {
ServerSocket ss = new ServerSocket(7777);
int cliente=1;
while(true) {
Socket s = ss.accept(); // espera una conexión de un cliente
PrintWriter out=new PrintWriter(s.getOutputStream(),true);
System.out.println("Eres el cliente " + cliente++);
s.close();
}
}
}
● Servidor iterativo: continúa atendiendo a nuevos
clientes
● A cada uno le envía una cadena con su número de cliente
y después cierra el socket
Redes: Tema 3 25
5. Sockets UDP
● Con UDP no se establece “conexión” entre cliente
y servidor
● El emisor indica explicitamente la dirección IP y el
puerto del origen y del destino en cada paquete
● El receptor ha de extraer del paquete recibido la
dirección IP y el puerto del emisor
● Los datos transmitidos pueden llegar fuera de
orden o incluso perderse
Redes: Tema 3 26
Comunicaciones UDP
Clase DatagramPacket
● Constructores
● DatagramPacket(byte buf[ ], int longitud)
● Crea un datagrama UDP a partir de ese buffer y con esa
longitud
● DatagramPacket(byte buf[ ], int longitud,
InetAddress dirIP, int puerto)
● Crea un datagrama UDP con ese buffer y de esa longitud
para enviarlo a la dirección IP y puerto que se indican
Redes: Tema 3 27
Comunicaciones UDP
Clase DatagramSocket
● Constructores
● DatagramSocket()
● Crea un socket UDP que escucha en un puerto libre
● DatagramSocket(int puerto)
● Crea un socket UDP que escucha en ese puerto
Redes: Tema 3 28
Comunicaciones UDP
Clase DatagramSocket
● Algunos métodos importantes
● send(DatagramPacket p)
● Envía un datagrama
● El DatagramPacket incluye los datos a enviar, su
longitud y la dirección IP y el puerto del destino
● receive(DatagramPacket p)
● Recibe datagramas. El método es bloqueante
● Cuando el método retorna, el buffer
DatagramPacket contiene los datos recibidos y la
dirección IP y puerto de quien envía el datagrama
● close()
Redes: Tema 3 29
Comunicaciones UDP
Clase DatagramPacket
Métodos
remoto
● getAddress( ) ● setAddress(InetAddress)
● getPort( ) ● setPort(int)
● getData( ) ● setData(byte[ ])
● getLength( ) ● setLength(int)
Redes: Tema 3 30
Cliente UDP
import java.net.*;
import java.io.*;
public class ClienteUDP{
public static void main(String[] args) throws IOException {
DatagramSocket s = new DatagramSocket();
InetAddress dir = InetAddress.getByName("zoltar.redes.upv.es");
String msg = "Hola, esto es un mensaje\n";
byte[] buf = new byte[256];
buf = msg.getBytes();
DatagramPacket p = new DatagramPacket(buf, buf.length, dir, 7777);
s.send(p);
s.receive(p); // se bloquea hasta que recibe un datagrama
System.out.write(p.getData());
s.close();
}
}
● El cliente envía un datagrama a un servidor e
imprime la respuesta
Redes: Tema 3 31
Servidor UDP
import java.net.*;
import java.io.*;
public class ServidorUDP{
public static void main(String[] args) throws IOException {
DatagramSocket s = new DatagramSocket(7777);
DatagramPacket p = new DatagramPacket(new byte[256], 256);
s.receive(p); // se bloquea hasta que recibe un datagrama
p.setAddress(p.getAddress());
p.setPort(p.getPort());
s.send(p);
s.close();
}
}
● Envía de vuelta el datagrama recibido, sin modificarlo, a
la dirección IP y puerto de origen
● Sólo procesa un cliente y acaba
Redes: Tema 3 32
6. Servidores concurrentes
En Java, la concurrencia la conseguimos
usando hilos de ejecución
Clase Thread
Ejemplo de uso:
● Se define una clase class Hilos extends Thread {
derivada de Thread int id;
public Hilos(int i) {id=i;}
public void run() {
● Código a ejecutar en for(int i=0;i<100;i++) {
cada hilo dentro del System.out.print(id);
try {sleep(100);}
método run() catch(InterruptedException e) {}
}
● Se lanza el hilo con }
start() public static void main(String args[]) {
for(int i=0;i<3;i++) new Hilos(i).start();
}
}
Redes: Tema 3 33
Servidores concurrentes
● Diversos hilos de ejecución:
● En el hilo principal se ejecuta permanentemente
el método accept()
● Espera el establecimiento de nuevas conexiones
● Para cada cliente que se conecta, se lanza un
nuevo hilo de ejecución para gestionar esa
conexión
Cliente 1 Maestro
Servidor 1
Cliente 2
Servidor 2
Cliente 3 Servidor 3
Redes: Tema 3 34
Identificación de los sockets
● Ahora tenemos varios sockets asociados al mismo puerto
● Para identificar al socket destino hay que tener en cuenta la
dirección (dir. IP + puerto) del socket origen
IP:62.3.3.3
Puerto: 80 IP:152.2.2.2
IP:62.3.3.3 Puerto: 2115
IP:128.1.1.1 Puerto: 80
Maestro servidor 1
servidor 2
Puerto: 1245 socket
socket
socket
Transporte
cliente 1 cliente 2
Red
socket socket
Transporte Enlace Transporte
Red Físico Red
Enlace Enlace
Físico Internet Físico
Redes: Tema 3 35
Servidor concurrente TCP
import java.net.*;
import java.io.*;
class SCTCP extends Thread {
Socket id;
public SCTCP(Socket s) {id=s;}
public void run() {
try {
PrintWriter out=new PrintWriter(id.getOutputStream(),true);
while(true){
out.println(System.currentTimeMillis());
sleep(100);
}
} catch(Exception e) {}
}
public static void main(String args[]) throws IOException{
ServerSocket ss=new ServerSocket(8888);
while(true) new SCTCP(ss.accept()).start();
}
}
● Le envía a cada cliente el tiempo transcurrido, en
milisegundos, desde medianoche de 1/1/1970 UTC
Redes: Tema 3 36
7. Ejemplos
Micro-servidor web iterativo
import java.net.*; import java.util.*; import java.io.*;
class ServidorWeb {
public static void main(String args[]) throws Exception{
byte[] buffer = new byte[1024]; int bytes;
ServerSocket ss=new ServerSocket(7777);
while(true) {
Socket s=ss.accept(); // espero a que llegue un cliente
BufferedReader in=new BufferedReader(new
InputStreamReader(s.getInputStream()));
PrintWriter out=new PrintWriter(s.getOutputStream(),true);
StringTokenizer tokens = new StringTokenizer(in.readLine());
tokens.nextToken(); // esto debe ser el "GET"
String archivo = "."+tokens.nextToken(); // esto es el archivo
FileInputStream fis = null; boolean existe = true;
try {fis = new FileInputStream(archivo);} // comprobamos si existe
catch (FileNotFoundException e) {existe = false;}
if (existe && archivo.length()>2)
while((bytes = fis.read(buffer)) != -1 ) // enviar archivo solicitado
s.getOutputStream().write(buffer, 0, bytes);
else out.println("<html><body><h1>404 Not Found</h1></body></html>");
s.close();
}
}
}
Redes: Tema 3 37
Micro-servidor web iterativo
El servidor no implementa
el protocolo HTTP
correctamente
Funciona gracias a que el
navegador se adapta
Redes: Tema 3 38
Servidor multiprotocolo
● Un servidor que proporciona
diversos servicios:
● Ejemplo: servidor de eco
TCP y UDP en la misma Inicio
aplicación
● Se lanzan varios hilos de Servicio A Servicio B Servicio C
ejecución para que un
bloqueo en un accept() o
en un receive() no
bloquee el funcionamiento
de los otros servicios
Redes: Tema 3 39
Servidor multiprotocolo
import java.net.*; import java.io.*;
class ServicioA extends Thread {
static ServerSocket ss;
public ServicioA(ServerSocket s) {ss=s;}
public void run() {
try {
Socket id=ss.accept();
new ServicioA(ss).start();
PrintWriter salida=new PrintWriter(id.getOutputStream(),true);
while(true) {
salida.println(System.currentTimeMillis()+" milisegundos");
sleep(100);
} class Multiprotocolo {
}catch(Exception e) {} public static void main(String args[])
} throws IOException {
} ServerSocket ssA=new ServerSocket(7788);
ServerSocket ssB=new ServerSocket(8877);
class ServicioB extends Thread { new ServicioA(ssA).start();
static ServerSocket ss; new ServicioB(ssB).start();
public ServicioB(ServerSocket s) {ss=s;} }
public void run() { }
try{
Socket id=ss.accept();
new ServicioB(ss).start();
PrintWriter salida=new PrintWriter(id.getOutputStream(),true);
while(true) {
salida.println(System.currentTimeMillis()/1000+ " segundos");
sleep(100);
}
}catch(Exception e) {}
}
}
Redes: Tema 3 40