Computing">
Nothing Special   »   [go: up one dir, main page]

Sockets

Descargar como pdf o txt
Descargar como pdf o txt
Está en la página 1de 145

Instituto Politécnico Nacional

Escuela Superior de Cómputo


Ingeniería en Sistemas Computacionales

Aplicaciones para Comunicaciones en Red

Sockets de flujo

M. en C. Sandra Ivette Bautista Rosales


¿Qué es un socket?

Aplicación Aplicación

Proceso Proceso

Proceso Proceso

Proceso Proceso

2
¿Qué es un socket?

Aplicación Aplicación

Proceso Proceso

Proceso Proceso
Cliente Servidor

Proceso Proceso

3
¿Qué es un socket?

Aplicación Aplicación

Proceso Proceso

Proceso Proceso
Cliente Servidor

Proceso Proceso

Aplicaciones para Comunicaciones en Red 4


M. en C. Sandra Ivette Bautista Rosales
¿Qué es un socket?

Aplicación Aplicación

Proceso Proceso
S

Proceso Proceso
Cliente S Servidor

Proceso Proceso
S

5
¿Qué es un socket?
• Aparecieron a principios de los 80’s con el sistema UNIX de
Berkeley
– Con el fin de proporcionar un medio de comunicación a
los procesos.
• Es un punto de comunicación por el cual un proceso puede
emitir o recibir información
• En el interior de un proceso, un socket se identifica por un
descriptor de la misma naturaleza que los que identifican a
los archivos
– SD: Es un número entero asociado a un fichero (archivo)
abierto (conexión de red, una terminal, etc.)

6
Modelo de referencia TCP/IP [1]

Modelo de referencia OSI [1]

7
Interfaz de Sockets
• Socket: Interfaz de programación (API) sobre el
nivel de transporte
– Abstracción que facilita al programador el acceso a los
servicios y recursos del nivel de transporte
– Ofrece un servicio punto a punto entre emisor y
receptor

Los procesos
de los
Los procesos protocolos de
de las transporte
aplicaciones forman parte
residen en el del S.O.
espacio de
usuario

8
Pila de protocolos TCP/IP
• Nivel de transporte:
– Servicio de envío de datos extremo a
extremo
– Hace uso de servicios del nivel de red
(IP)
• Protocolo TCP:
– Servicio orientado a conexión, fiable,
ordenado, con control de flujo y errores
• Requiere establecimiento previo de una
conexión entre ambos extremos
• Ofrece flujo permanente entre los extremos
en ambas direcciones
• Controla la recepción en orden, completa y
sin errores, gestionando el reenvío de
paquetes perdidos
9
Pila de protocolos TCP/IP
• Protocolo UDP:
– servicio no orientado a conexión,
no fiable y sin control de flujo y
errores
– Cada mensaje UDP (datagrama) es
independiente y se trata de forma
aislada
– No se garantiza la entrega de
datagramas enviados ni que estos
lleguen en orden
10
Primitivas para la utilización de
sockets
• Secuencia de primitivas para la utilización de
sockets que el cliente y el servidor tienen que
usar para ambos tipos de servicio:
– Orientado a conexión
– No orientado a conexión

Diagrama de primitivas de sockets

11
Dominio de un socket
• Representa una familia de protocolos
• Una familia o dominio de la conexión, agrupa
todos aquellos sockets que comparten
características comunes y con los cuáles se
puede establecer una comunicación.
• Un socket está asociado a un dominio desde su
creación.
• Existen diferentes dominios de comunicación,
los formatos reconocidos actualmente son:

12
Dominio de un socket
• AF_UNIX, AF_LOCAL
• AF_INET
• AF_INET6
• AF_IPX
• AF_NETLINK Los servicios de sockets
• AF_X25 son independientes del
dominio
• AF_AX25
• AF_ATMPVC
• AF_APPLETALK
• AF_PACKET
• AF_ALG
13
Tipos de sockets
• Define las propiedades de las comunicaciones en
las que se ve envuelto un socket, esto es, el tipo
de comunicación que se puede dar entre cliente y
servidor.
• Estas pueden ser:
– Fiabilidad de la transmisión: Ningún dato transmitido
se pierde
– Conservación del orden de los datos. Los datos llegan
en el orden en que han sido emitidos.
– No duplicación de datos. Solo llega a destino un
ejemplar de cada dato emitido
14
Tipos de sockets
– El «modo conectado» en la comunicación
– Envío de mensajes urgentes

• SOCK_STREAM
• SOCK_DGRAM
• SOCK_RAW
• SOCK_SEQPACKET
• SOCK_RDM
• SOCK_PACKET
15
Interfaz de Sockets
• Puertos: identificadores usados para asociar los datos
entrantes a un proceso concreto de la máquina.
– Usados tanto en TCP como en UDP
– Números de 16 bits
– 0-1023: reservados por convenio (“puertos bien
conocidos”)
• Asignados a los servidores de servicios básicos

– 1024-65535: uso libre


• Son los usados con los clientes al establecer conexiones
• Suelen asignarse de forma aleatoria
16
Interfaz de Sockets
• Direccionamiento: Para comunicarse con otro
proceso usando sockets debe conocerse:
1. Dirección IP (32 bits) de la máquina donde se
ejecuta el proceso
• Alternativamente, su nombre para consultar servicio de
nombre DNS (traducción dominio IP)
2. No. De puerto (TCP o UDP) que utiliza el proceso
en su máquina
• Por lo tanto, la interfaz de sockets no ofrece
transparencia de localización
17
Relación lógica entre aplicaciones
sockets, protocolos y puertos

Aplicaciones
Referencias

Sockets TCP Sockets UDP

Ligas del socket


con el puerto
1 a 65535 puertos TCP 1 a 65535 puertos UDP

TCP UDP
IP

18
Implementación de sockets

19
Sockets bloqueantes y no bloqueantes
• No se trata de sockets diferentes realmente, son
solo opciones para las formas en las que trabajan
• Los sockets bloqueantes son aquellos que se
quedan esperando hasta que existe información
para establecer una conexión, leer o escribir un
mensaje
• Los sockets no bloqueantes interrogan si hay
datos para procesar y en caso de que no se así,
continúan con el código
• El socket no bloqueante se definen modificando
sus opciones
20
SOCKETS ORIENTADOS A CONEXIÓN NO
BLOQUEANTES

• Operaciones de entrada/salida son por lo general bloqueantes


y esto también ocurre cuando se utilizan con sockets.

• Cuando se crea un socket por medio de la llamada socket() el


kernel lo establece como bloqueante.

Proceso bloqueante à El proceso pasa al


estado dormido, esperando que se
satisfaga alguna condición que permita
que se complete la operación.

21
SOCKETS ORIENTADOS A CONEXIÓN NO
BLOQUEANTES
También implica cundo se realizan algunas operaciones o llamadas sobre
un socket:

• Operaciones de salida (write(),


send(), sendto, connect(), …) • Operaciones de entrada
(read, recv, recvfrom, …)
• Ej. Sobre un socket de flujo
• Sobre un socket de flujo
• El kernel copia los datos del
buffer de la aplicación en el • y no hay datos
buffer de envío del socket disponibles en el buffer
de recepción del socket,
• si no queda espacio en
este buffer, el proceso se
el proceso pasa a estado
bloquea hasta que haya dormido hasta que
suficiente espacio. lleguen datos.

22
EJEMPLO

Aplicación Aplicación

Proceso Proceso
Cliente Servidor

23
EJEMPLO

Aplicación Aplicación

Proceso Proceso
Cliente Servidor

24
EJEMPLO

Aplicación Aplicación

recv()

Proceso Proceso
Cliente Servidor

25
EJEMPLO

Aplicación Aplicación

recv()

Proceso Proceso
Cliente Servidor

26
EJEMPLO

Aplicación Aplicación

recv()

Proceso Proceso
Cliente Servidor

send()

27
EJEMPLO

Aplicación Aplicación

recv()

Proceso Proceso
Cliente Servidor

send()

28
EJEMPLO

Aplicación Aplicación

recv()

Proceso Proceso
Cliente Servidor

send()

29
EJEMPLO

Aplicación Aplicación

recv()

Proceso Proceso
Cliente Servidor

send()

30
EJEMPLO

Aplicación Aplicación

No
bloqueante

recv()

Proceso Proceso
Cliente Servidor

send()

31
¿CÓMO ESTABLECER UN SOCKET ORIENTADO
A CONEXIÓN COMO NO BLOQUEANTE?
Nota:
Es recomendable emplear algún mecanismo que nos permita realizar
estas funciones de forma no bloqueante y así poder realizar otras tareas
en vez de esperar hasta que los datos estén disponibles.

Beneficios:
• «interrogar» al socket por su
Mecanismos :
información.
• fcntl()
• Si intentas leer de un socket no
bloqueante y no hay datos • select()
disponibles • Polling
• devolverá un -1 y asignará a • Asíncronos
errno el valor
EWOULDBLOCK
32
¿CÓMO ESTABLECER UN SOCKET ORIENTADO
A CONEXIÓN COMO NO BLOQUEANTE?
Ventajas de sockets bloqueantes y no bloqueantes
Bloqueantes No bloqueantes:
• Permiten esperar eventos de • Permiten que un proceso (ej.
entrada salida fácilmente sin servidor ) atienda a múltiples
ocupar tiempo de CPU. clientes
Desventaja • Las funciones de entrada y
salida que no pueden realizar
• son más lentos que los no
su tarea por falta de datos
bloqueantes
retornan inmediatamente y
devuelven un código de error.
• Permiten la combinación de
sockets con multi-hilos.

33

FUNCIÓN
Es un acrónimo de ‘File Control’
fcntl()
• Permite llevar a cabo distintas operaciones de control sobre
descriptores
• La sintáxis es la siguiente:

Argumentos que necesita el


Descriptor del socket sobre
comando, para establecer el
el cual se va a realizar alguna
socket como no bloqueante será
operación
O_NONBLOCK
Determina el comando que se va a aplicar, para este
caso se usará el comando F_SETFL, el cual establece
los flag del descriptor al valor especificado en arg.
34
FUNCIÓN fcntl()
• Cada descriptor tiene un conjunto de flags que se obtiene utilizando la orden
(parámetro cmd) F_GETFL y que se obtienen utilizando la orden F_SETFL.
• Del conjunto de flags que puede manipular fcntl, los dos flags que afectan al
comportamiento de los sockets son los siguientes:
O_NONBLOCK E/S no bloqueante.
O_ASYNC E/S guiada por señales (signal-drive I/O)

Si nos centramos en la programación de aplicaciones en redes la función fcntl nos


permite hacer lo siguiente:
E/S dirigida mediante señales: Si activamos el flag de estado O_ASYNC utilizando
F_SETFL conseguimos que se genere la señal SIGIO cuando se modifica el estado
de un socket.
Entrada/Salida no bloqueante: Si activamos el flag O_NONBLOCK (utilizando una
vez más F_SETFL) conseguimos hacer no-bloqueante un socket.

35
FUNCIÓN fcntl()
Desventajas:
• Está en espera activa
• Consume tiempo innecesario de CPU ya que no realiza ninguna
operación

36
FUNCIÓN select()

Imagine la siguiente situación:

• Usted es un servidor y desea escuchar las conexiones entrantes, así


como mantener la lectura de las conexiones que ya tiene.

37
FUNCIÓN select()

Imagine la siguiente situación:

• Usted es un servidor y desea escuchar las conexiones entrantes, así


como mantener la lectura de las conexiones que ya tiene.
• No hay problema, ustedes dicen, sólo un accept() y un par de recv()…
No es tán fácil!

38
FUNCIÓN select()

Imagine la siguiente situación:

• Usted es un servidor y desea escuchar las conexiones entrantes, así


como mantener la lectura de las conexiones que ya tiene.
• No hay problema, ustedes dicen, sólo un accept() y un par de recv()…
No tan rápido!
• ¿Qué pasa si usted está bloqueado en un una llamada accept()?
¿Cómo vas a hacer un recv() de datos al mismo tiempo?

39
FUNCIÓN select()

Imagine la siguiente situación:

• Usted es un servidor y desea escuchar las conexiones entrantes, así


como mantener la lectura de las conexiones que ya tiene.
• No hay problema, ustedes dicen, sólo un accept() y un par de recv()…
No tan rápido!
• ¿Qué pasa si usted está bloqueado en un una llamada accept()?
¿Cómo vas a hacer un recv() de datos al mismo tiempo?
• à"Usar sockets no bloqueo" De ninguna manera! Ocupar toda la
CPU. ¿Entonces que?

40
Función select()

• Select() le da el poder de controlar varios sockets al mismo tiempo.


Podrás saber cuáles sockets están listos para la lectura, cuáles están
listos para la escritura, y qué sockets han planteado excepciones, si
realmente quieres saber eso.

Desventajas:
• Aunque es una función muy portable, es uno de los métodos más
lentos para la vigilancia de sockets.

41
Función select()
• La sintaxis es la siguiente

Se proveen 4 macros para manejo del conjunto de descriptores:

1 • Agrega un descriptor a un conjunto


2 • Borra un descriptor de un conjunto
3 • Verifica si un descriptor está dentro de un conjunto
4 • Limpia un conjunto de descriptores
42
Función select()

Los macros se utilizan luego del retorno de select()


para verificar cual descriptor
cambio su estado.

Timeval

• Permite monitorear un conjunto de descriptores de


sockets
• Nos avisa cuáles tienen datos para:
• Leer
• Escribir
• Excepción

43
Mecanismos Polling
Tarea: Mecanismos Polling
• Cuáles son
• En qué consisten
• Ventajas y desventajas

44
API java

https://docs.oracle.com/javase/8/docs/api

45
Clase Socket
• Implementa un socket de flujo del lado del
cliente
• Se le llama simplemente socket
• El trabajo del Socket lo desempeña
principalmente una instancia de la clase
SocketImpl
• Se encuentra en java.net

46
Constructores principales de Socket
• Socket(); crea un socket de flujo desconectado
usando el tipo por defecto de SocketImpl.
• Socket(InetAddress address, int port); Crea un
socket de flujo y lo conecta a un número de
puerto en una IP definida
• Socket(InetAddress address, int port, InetAddress
localAddress, int localPort); Crea un socket de flujo,
ligado a una dirección y puerto local y lo conecta
a un número de puerto en una IP definida remota

47
Métodos principales de Socket
• bind(SocketAddress bindport); liga al socket con algún
puerto local.
• close(); Cierra el socket.
• connect(SocketAddress endpoint); conecta al socket
con el servidor
• connect(SocketAddress endpoint, int timeout);
conecta al socket con el servidor definiendo un
tiempo máximo para la conexión

48
Clase ServerSocket
• Implementa un socket de servidor de flujo
• Una instancia de esta clase espera por
solicitudes de conexión en la red
• El trabajo del ServerSocket lo desempeña
principalmente una instancia de la clase
SocketImpl
• Se encuentra en java.net

49
Constructores principales de
ServerSocket()
• ServerSocket(); crea un socket de servidor.
• ServerSocket(int port); crea un socket de servidor ligado a
un puerto.
• ServerSocket(int port, int backlog); crea un socket de
servidor ligado a un puerto con una cola de conexiones
específica.
• ServerSocket(int port, int backlog, InetAddress bindAddr);
crea un socket de servidor ligado a un puerto con una
cola de conexiones específica y una dirección IP local.

50
Métodos principales de ServerSocket
• accept(); escucha esperando una conexión en la
red.
• bind(SocketAddress endpoint); liga al ServerSocket
a una dirección IP y número de puerto
específico.
• close(); Cierra el socket.

51
ServerSocket() y Bind()
ServerSocket s = new ServerSocket();
InetSocketAddress dir = new InetSocketAddres(1234);
s.bind(dir);
ó
ServerSocket s = new ServerSocket(1234);

52
Flujos en java

Volcan Merapi, isla de Java


53
Licencia Creative Common CCO, skeeze@pixabay.com
Flujos en java
• Paquete java.io
Entrada - lectura Salida - escritura

Programa Fuente Programa Fuente

Flujo Flujo

• Flujos binarios y de caracter

54
Flujos binarios
• Byte (8bits)
• Mas primitivos y portables
• Los demás flujos lo usan
• Flujo de bajo nivel
• InputStream y OutputStream

55
Flujos de caracteres
• char (16 bits)
• Codificación unicode
• Ideal para texto plano
• Reader y Write

56
InputStream

Audio ByteArray File Piped Filter Secuence StringBuffer Object


InputStream InputStream InputStream InputStream InputStream InputStream InputStream InputStream

Diagrama
OutputStream

de clases
ByteArray File Filter Piped Object
OutputStream OutputStream OutputStream OutputStream OutputStream

principales
Reader

Buffered CharArray InputStream Filter Piped String


Reader reader Reader Reader Reader Reader

Writer

Buffered CharArray OutputStream


Filter Writer Piped Writer String Writer Print Writer
Writer Writer Writer

57
Lectura y escritura
• Abrir
• Leer o escribir
• Cerrar

58
Lectura, ImputStream
• int read(); Lee el próximo byte del flujo
representado en un entero. Devuelve -1 si no
quedan mas datos que leer.
• int read(byte[] b); Lee un arreglo de bytes del
flujo.
• int read(byte[] b, int off, int len); Lee un arreglo de
bytes del flujo, desde y hasta la posición
indicada

59
Lectura, Reader
• int read() – Lee el próximo carácter del flujo
representado en un entero. Devuelve -1 si no
quedan mas datos que leer.
• int read(char[] cbuf) – Lee un arreglo de
caracteres del flujo.
• int read(char[] cbuf, int off, int len) – Lee un
arreglo de caracteres del flujo, desde y hasta
la posición indicada.

60
Escritura, OutputStream
• void write(int b); Escribe un solo byte en el flujo.
• void write(byte[] b); Escribe un arreglo de bytes
en el flujo.
• void write(byte[] b, int off, int len); Escribe una
porción de un arreglo de bytes en el flujo.

61
Escritura, Writer
• void write(int c); Escribe un solo carácter en el
flujo.
• void write(char[] cbuf); Escribe un arreglo de
caracteres en el flujo.
• void write(char[] cbuf, int off, int len); Escribe una
porción de un arreglo de caracteres en el flujo

62
Entrada y salida estándar
• Clase System dentro de java.lang
• InputStream in (InputStream); Flujo de entrada
estándar. Típicamente corresponde al teclado.
• PrintStream out (OutputStream); Flujo de salida
estándar. Típicamente corresponde a la pantalla.
• PrintStream err (OutputStream); Flujo de salida
estándar de errores. Típicamente corresponde a
la pantalla.
• Pueden ser redirigidos

63
Ejemplo
• Realizar una aplicación con una arquitectura
cliente/servidor en java con sockets
bloqueantes
• El cliente se conecta con el servidor y recibe
un mensaje

64
Programa de eco
Cliente Servidor
• Crea el flujo de entrada
Solicitud de • Pide información sobre el servidor • Crea el socket
datos • Lo liga a un puerto
Creación del
ServerSocket
• Crea el socket
• Se conecta con el servidor
Crea el • Crea el flujo de lectura
Socket • Lee el mensaje recibido y lo imprime • Espera una conexión
• Establece una conexión
• Envía un mensaje
• Cierra la comunicación con el
• Cierra los flujos Ciclo infinito cliente
Cierre del • Cierra el socket
cliente

65
Servidor (1/3)
• Primero, necesitamos las bibliotecas
import java.net.*;
import java.io.*;

• Ahora, se define la clase y creamos el socket. Lo


ligamos al puerto 1234
public class SHola {
public static void main(String[] args){
try{
ServerSocket s = new ServerSocket(1234);
System.out.println("Esperando cliente ...");

La creación de sockets siembre debe de hacerse


dentro de un bloque try-catch
66
Servidor (2/3)
• El servidor espera dentro de un ciclo infinito la
solicitud de conexión de un cliente
for(;;){
Socket cl = s.accept();
System.out.println("Conexión establecida desde “ +
cl.getInetAddress()+":"+cl.getPort());
• Definimos el mensaje a enviar y ligamos un
PrintWriter a un flujo de salida de carácter
String mensaje ="Hola mundo";
PrintWriter pw = new PrintWriter(new OutputStreamWriter(cl.getOutputStream()));
pw.println(mensaje);
pw.flush();

67
Servidor (3/3)
• Cerramos el flujo, cerramos el socket, termínanos el
ciclo for y el bloque try-catch y cerramos la clase
pw.close();
cl.close();
}//for
}catch(Exception e){
e.printStackTrace();
}//catch
}//main
}

68
Cliente (1/3)
• Agregamos las bibliotecas
import java.net.*;
import java.io.*;

• Definimos la clase y creamos la función main()


public class Cliente {
public static void main(String[] args){

• Creamos el bloque try-catch y definimos un flujo


de lectura de la entrada estándar
try{
BufferedReader br1 = new BufferedReader(new InputStreamReader(System.in));

69
Cliente (2/3)
• A partir del flujo de lectura obtenemos del
usuario la dirección y puerto del servidor
System.out.printf("Escriba la dirección del servidor: ");
String host = br1.readLine();
System.out.printf("\n\nEscriba el puerto:");
int pto = Integer.parseInt(br1.readLine());
• Creamos el socket
Socket cl = new Socket(host,pto);
• Creamos un flujo de carácter ligado al socket para
recibir el mensaje
BufferedReader br2 = new BufferedReader(new InputStreamReader(cl.getInputStream()));

70
Cliente (3/3)
• Leemos el mensaje recibido
String mensaje = br2.readLine();
System.out.println("Recibimos un mensaje desde el servidor");
System.out.println("Mensaje:"+mensaje);
• Cerramos los flujos, el socket y terminamos el programa
br1.close();
br2.close();
cl.close();
}catch(Exception e){
e.printStackTrace();
}
}
}

71
Ejemplo 2: envío de archivos
• Crear una aplicación para el envío de un
archivo desde el cliente al servidor
• Se usará un socket orientado a conexión
bloqueante
• Los archivos podrán ser de texto o binarios

72
Envío de archivos
Cliente Servidor
•Crea el flujo de entrada •Crea el socket
Solicitud de •Pide información sobre el servidor Creación del
•Lo liga a un puerto
datos ServerSocket

•Espera una conexión


•Crea el socket y se conecta con el servidor
•Establece una conexión
•Elige el archivo a enviar
•Define un flujo para leer del socket
Crea el Socket •Crea flujos para leer el archivo y para enviarlo por el socket Ciclo infinito
•Recibe los datos principales del archivo a recibir

•Lee un bloque de datos del archivo •Define un flujo para escribir el archivo
•Los envía por el socket •Recibe los paquetes
Ciclo de envío •Calcula el porcentaje de progreso Ciclo de recepción •Los reescribe en el archivo
de paquetes de paquetes

•Cierra los flujos •Cierra el archivo


•Cierra el archivo •Cierra los flujos
Cierre del •Cierra el socket Cierre del •Cierra el socket
cliente servidor

73
Cliente (1/4)
• Se agregan las bibliotecas pertinentes, se define la clase, la función main()
y se inicia el bloque try-catch
import javax.swing.JFileChooser;
import java.net.*;
import java.io.*;
public class ClienteArchivo {
public static void main(String[] args){
try{
• Se define un flujo de entrada para obtener los datos del servidor
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
System.out.printf("Escriba la dirección del servidor:");
String host = br.readLine();
System.out.printf("\n\nEscriba el puerto:");
int pto = Integer.parseInt(br.readLine());

• Se define el socket
Socket cl = new Socket(host, pto);

74
Cliente (2/4)
• Se usa un JFileChooser() para elegir el archivo a enviar
JFileChooser jf = new JFileChooser();
int r = jf.showOpenDialog(null);
• Una vez seleccionado, se obtienen sus datos principales
if (r==JFileChooser.APPROVE_OPTION){
File f = jf.getSelectedFile(); //Manejador
String archivo = f.getAbsolutePath(); //Dirección
String nombre = f.getName(); //Nombre
long tam = f.length(); //Tamaño
• Se definen dos flujos orientados a bytes, uno se usa para
leer el archivo y el otro para enviar los datos por el socket
DataOutputStream dos = new DataOutputStream(cl.getOutputStream());
DataInputStream dis = new DataInputStream(new FileInputStream(archivo));

75
Cliente (3/4)
• Enviamos los datos generales del archivo por el socket
dos.writeUTF(nombre);
dos.flush();
dos.writeLong(tam);
dos.flush();
• Leemos los datos contenidos en el archivo en paquetes de
1024 y los enviamos por el socket
byte[] b = new byte[1024];
long enviados = 0;
int porcentaje, n;
while (enviados < tam){
n = dis.read(b);
dos.write(b,0,n);
dos.flush();
enviados = enviados+n;
porcentaje = (int)(enviados*100/tam);
System.out.print("Enviado: "+porcentaje+"%\r");
}//While
76
Cliente (4/4)
• Cerramos los flujos, el socket, terminamos
bloques y cerramos la clase
System.out.print("\n\nArchivo enviado");
dos.close();
dis.close();
cl.close();
}//if
}catch(Exception e){
e.printStackTrace();
}
}
}

77
Servidor (1/3)
• Agregamos bibliotecas, definimos la clase , el main(),
iniciamos el bloque try y definimos el socket
import java.net.*;
import java.io.*;

public class ServidorArchivo {


public static void main(String[] args){
try{
ServerSocket s = new ServerSocket(7000);
• Iniciamos el ciclo infinito y esperamos una conexión
for(;;){
Socket cl = s.accept();
System.out.println("Conexión establecida desde"+cl.getInetAddress()+":"+cl.getPort());
• Definimos un flujo de nivel de bits de entrada ligado al
socket
DataInputStream dis = new DataInputStream(cl.getInputStream());
78
Servidor (2/3)
• Leemos los datos principales del archivo y creamos
un flujo para escribir el archivo de salida
byte[] b = new byte[1024];
String nombre = dis.readUTF();
System.out.println("Recibimos el archivo:"+nombre);
long tam = dis.readLong();
DataOutputStream dos = new DataOutputStream(new FileOutputStream(nombre));
• Preparamos los datos para recibir los paquetes de
datos del archivo
long recibidos=0;
int n, porcentaje;

79
Servidor (3/3)
• Definimos el ciclo donde estaremos recibiendo los datos enviados
por el cliente
while(recibidos < tam){
n = dis.read(b);
dos.write(b,0,n);
dos.flush();
recibidos = recibidos + n;
porcentaje = (int)(recibidos*100/tam);
System.out.print("\n\nArchivo recibido.");
}//While
• Cerramos los flujos, el socket y el resto del programa
dos.close();
dis.close();
cl.close();
}
}catch(Exception e){
e.printStackTrace();
}//catch
}
}

80
Práctica
• Modificar el archivo anterior para que permita
el envío de múltiples archivos

81
Sockets en C

Sockets bloqueantes
Cliente de eco
• Crea un socket de flujo usando socket()
• Establece la conexión usando connect()
• Envía un mensaje empleado send()
• Recibe una respuesta con recv()
• Cierra la conexión usando close()

83
Cliente de eco
Biblioteca MensajeError.h
#include <stdio.h>
#include <stdlib.h>

void mensajeFinalError(const char *mensaje){


fputs(mensaje,stderr);
fputc('\n',stderr);
exit(1);
}
void mensajeFinalSistema(const char *mensaje){
perror(mensaje);
exit(1);
}

84
Cliente de eco (1/5)
Segmento #include y análisis inicial
#include <stdio.h> int main(int argc, char** argv) {
#include <stdlib.h>
#include <string.h>
if (argc < 3|| argc >4)
#include <unistd.h> mensajeFinalError("Uso: EcoTCPCliente
#include <sys/types.h> <Dirección del servidor> <Palabra de eco> [<Puerto>]");
#include <netinet/in.h>
#include <arpa/inet.h>
char *servIP = argv[1];
#include "MensajeError.h" char *cadenaEco = argv[2];
#define TAMBUFER 2000 //Argumento opcional, se agrega por defecto
in_port_t puerto = (argc == 4) ? atoi(argv[3]) : 7;

85
Cliente de eco (2/5)
Creación del socket de flujo
//Crea el socket del cliente TCP
int s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if(s < 0){
mensajeFinalError("Error de apertura del conector");
}

86
Prototipo socket()
#include <sys/types.h>
#include <sys/socket.h>

Int socket(int af, int type, int protocol)

87
Familia de direcciones (1/2)
Familia Descripción
AF_LOCAL Es otro nombre para AF_UNIX
AF_INET Protocolo internet DARPA (TCP/IP)
AF_INET6 Protocolo internet versión 6
AF_PUP Antigua red Xerox
AF_CHAOS Red Chaos del MIT
AF_NS Arquitectura Xerox Network System
AF_ISO Protocolos OSI
AF_ECMA Red European Computer Manufactures
AF_DATAKIT Red Datakit de AT&T
AF_CCITT Protocolos del CCITT, por ejemplo X.25
AF_SNA System Network Architecture (SNA) de IBM
AF_DECnet Red DEC
88
Familia de direcciones (2/2)
Familia Descripción
AF_IMPLINK Antigua interfaz de enlace 1822 Interface Message Processor
AF_DLI Interfaz directa de enlace
AF_LAT Interfaz de teminales de red de área local
AF_HYLINK Network Syste, Córporation Hyperchannel
AF_APPLETALK Red AppleTalk
AF_ROUTE Comunicación con la capa de encaminamiento del núcleo
AF_LINK Acceso a la capa de enlace
AF_XTP eXpress Transfer Protocol
AF_COIP Connection-oriented IP (ST II)
AF_CNT Computer Network Tecnology
AF_IPX Protocolo Internet de Novell

89
Tipos de semántica de la comunicación
• SOCK_STREAM, sockets de flujo
• SOCK_DGRAM, sockets de datagrama
• SOCK_RAW, sockets crudos
• SOCK_SEQPACKET, conector no orientado a conexión
pero fiable de longitud fija (solo en AF_NS)
• SOCK_RDM, conector no orientado a conexión pero
fiable y secuencial (no implementado pero se puede
simular a nivel de capa de usuario)

90
Parámetro protocolo
• Especifica el protocolo particular
• Normalmente cada tipo de protocolo tiene
relacionado un solo protocolo, en caso
contrario, aquí se especificaría.
• Un valor de 0 deja que el sistema decida el
protocolo.

91
Cliente de eco (3/5)
Preparando la dirección y conectando
//Creamos la dirección del servidor de entrada
struct sockaddr_in dirServ;
memset(&dirServ,0,sizeof(dirServ));
dirServ.sin_family = AF_INET;
int valRet = inet_pton(AF_INET, servIP,&dirServ.sin_addr.s_addr);
if(valRet == 0)
mensajeFinalError("Dirección del servidor erronea");
else if(valRet < 0)
mensajeFinalError("Error en el inet_pton()");
dirServ.sin_port = htons(puerto);
//Establecemos la comunicación con el servidor de eco
if(connect(s, (struct sockaddr*) &dirServ,sizeof(dirServ))<0)
mensajeFinalError("Error en la conexión");
size_t longCadenaEco = strlen(cadenaEco);

92
Formas de direcciones de la familia
AF_INET (direcciones de internet)
struct in_addr{
u_long s_addr // 32 bits con la dirección IP
};
Struct sockaddr_in{
short sin_family; //AF_INET
u_short sin_port; //16 bits para el puerto
struct in_addr sin_addr;
char sin_zero [8]; //8 bytes no usados
};

93
Prototipo connect()
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h> //Familia AF_INET

int connect(int sfd, const void *addr, int addrlen);

94
Parámetros de connect()
• sdf es el descriptor del socket que da acceso al
canal.
• addr puntero a la estructura de la dirección
del conector.
• addrlen es el tamaño de la dirección en bytes.

95
connect()
• La estructura de la dirección depende de la
familia de conectores
• Si es SOCK_DGRAM, especifica la dirección del
conector pero no se conecta.
• Si es SOCK_STREAM, intenta conectarse con el
ordenador remoto.

96
Cliente de eco (4/5)
Enviando cadena al servidor
//Envia el mensaje al servidor
ssize_t numBytes = send(s,cadenaEco,longCadenaEco, 0);
if(numBytes< 0)
mensajeFinalError("Fallo el envio");
else if(numBytes != longCadenaEco)
mensajeFinalError("Número de bytes enviados erroneo");

97
Envío de un mensaje a un conector
• writev(), send(), sendto() y sendmsg()
• writev() es una generalidad de write() y se
puede usar para escribir en un archivo o en un
socket
• El resto solo se usan para sockets

98
writev()
#include <sys/uio.h>
ssize_t writev(int fildes, cons struct iovec *iov, size_t iovcnt)

• fildes es el descriptor del fichero o socket


• iov es el vector donde están los datos
• iovcnt nos dice cuantos datos se van a escribir.

99
send(), sendto() y sendmsg()
#include <sys/socket.h>

int send(int sfd, void buf, int len, int flags)


int sendto(int sfd, void buf, int len, int flags, void *to, int tolen);
Int sendmsg (int sfd, struct msghdr msg[], int flag);

• Los posibles valores de flag son 0 ó MSG_OOB, mensaje


urgente.
• msg[], son un arreglo de datos struc msghdr y permite enviar
un mensaje que está en varias secciones de memoria.

100
Cliente de eco (5/5)
Recibiendo respuesta del servidor
//Recibimos de vuelta la cadena desde el servidor
unsigned int totalBytesRec = 0;
while(totalBytesRec < longCadenaEco){
char bufer[TAMBUFER];
memset(bufer,0,TAMBUFER);
numBytes = recv(s,bufer,TAMBUFER, 0);
if(numBytes<0)
mensajeFinalError("Recepción fallida");
else if(numBytes==0)
mensajeFinalError("Conexión cerrada prematuramente");
totalBytesRec += numBytes;
printf("Recibido: %s\n",bufer);
}
close(s);
return 0;
} 101
Lectura de un mensaje a un socket
• readv(), recv(), recvto() y recvmsg()
• readv() es una generalidad de read() y se puede
usar para escribir en un archivo o en un socket
• El resto solo se usan para sockets y son un
espejo de las funciones anteriores.

102
Servidor de eco en C (1/6)
#include <stdio.h> void manejadorTCPCliente(int);
#include <stdlib.h>
#include <string.h> int main(int argc, char **argv){
#include <sys/types.h>
#include <sys/socket.h>
if(argc != 2) //Revisamos el número de argumentos
#include <netinet/in.h> mensajeFinalError("Uso: EcoTCPServidor
#include <arpa/inet.h> [<puerto>]");
#include "./MensajeError.h" in_port_t prtoServ = atoi(argv[1]);

#define MAXLISTA 5
#define TAMBUFER 1024

103
Servidor de eco en C (2/6)
//Creamos el socket de entrada
int sockServ;
if((sockServ = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP)) < 0)
mensajeFinalError("Fallo la apertura del socket");
//Se construye la estructura de la dirección
struct sockaddr_in dirServ; //Estructura para la dirección local
memset(&dirServ, 0 , sizeof(dirServ)); //Limpiamos la estructura
dirServ.sin_family = AF_INET; //Familia de direcciones IPv4
dirServ.sin_addr.s_addr = htons(INADDR_ANY); //Cualquier interfaz de entrada
dirServ.sin_port = htons(prtoServ); //Número de puerto

//Se enlaza a la dirección local


if(bind(sockServ, (struct sockaddr*)&dirServ, sizeof(dirServ))< 0)
mensajeFinalError("Error al enlazar");

104
Función bind()
#include <sys/socket.h>
#include <netinet/in.h> //Solo AF_INET

Int bind(int sfd, const void *addr, int addrlen);

105
Servidor de eco en C (3/6)
//Marcamos el socket para que pueda escuchar conexiones
if(listen(sockServ, MAXLISTA) < 0)

for(;;){//Lazo infinito
struct sockaddr_in dirCliente; //Dirección del cliente
//Obtenemos el tamaño de la estructura
socklen_t dirClienteTam = sizeof(dirCliente);

106
Servidor de eco en C (4/6)
//Esperamos que se conecte un cliente
int sockCliente = accept(sockServ,(struct sockaddr *)&dirCliente, &dirClienteTam);
if (sockCliente < 0)
mensajeFinalError("Fallo la conexión ");
//Se conecto un cliente
char nombreCliente[INET_ADDRSTRLEN];
if(inet_ntop(AF_INET, &dirCliente.sin_addr.s_addr, nombreCliente, sizeof(nombreCliente)) != NULL)
printf("Cliente conectado: %s/%d\n",nombreCliente,ntohs(dirCliente.sin_port));
else
puts("Inposible conectar el cliente");
manejadorTCPCliente(sockCliente);
}
}

107
Función listen()
#include <sys/socket.h>
#include <netinet/in.h> //Solo AF_INET

int listen(int sfd, int backlog);


• sfd es el descriptor de socket
• backlog el número de conexiones permitidas

108
Función accept()
#include <sys/socket.h>
int accept (int sfd, void *addr, int *addrlen)
• sfd es el descriptor de socket
• addr apuntador a la estructura local del socket
remoto
• addrlen es el tamaño de dicha estructura

109
Servidor de eco en C (5/6)
void manejadorTCPCliente(int sockCliente){
char bufer[TAMBUFER];

//Recibe mensaje del cliente


ssize_t numBytesRecibidos = recv(sockCliente, bufer, TAMBUFER, 0);
if(numBytesRecibidos < 0)
mensajeFinalError("Error en la lectura de datos recibidos");
//Envia los datos recibidos
while(numBytesRecibidos > 0){

110
Servidor de eco en C (6/6)
//Eco del mensaje
ssize_t numBytesEnviados = send(sockCliente, bufer, numBytesRecibidos, 0);
if(numBytesEnviados < 0)
mensajeFinalError("Error en el envio");
else if(numBytesEnviados == 0)
mensajeFinalError("Número de bytes enviado erroneo");
//Revisamos si hay mas datos a recibir
numBytesRecibidos = recv(sockCliente,bufer, TAMBUFER,0);
if(numBytesRecibidos < 0)
mensajeFinalError("Error en la lectura de datos recibidos");
}
close(sockCliente);
}

111
Sockets UDP

112
Sockets UDP
• En las comunicaciones basadas en datagramas (p.
ej. UDP), el paquete de datagramas contiene el
número de puerto de su destino y UDP encamina
el paquete a la aplicación apropiada.
• El API de Java para UDP proporciona una
abstracción del «paso de mensajes».
• Esto hace posible a un proceso emisor transmitir
un único mensaje a un proceso receptor.
• Los paquetes independientes que contienen esos
mensajes se denominan datagramas.
113
Sockets UDP
• Un datagrama enviado mediante UDP es
transmitido desde un proceso emisor a un
proceso sin reconocimiento de
recomprobaciones.
• Si tiene lugar un fallo, el mensaje puede no llegar.
• Un datagrama es transmitido entre procesos
cuando un proceso lo envía y otro proceso lo
recibe.
• Cualquier proceso que necesite enviar o recibir
mensajes debe en primer lugar crear un socket a
una dirección de Internet y a un puerto local.
114
Sockets UDP
• Un servidor enlazará ese socket a un puerto
servidor (uno que es conocido por los clientes
de manera que puedan enviarle mensajes).
• Un cliente enlaza su socket a cualquier puerto
local libre.
• El método receptor devuelve la dirección de
Internet y el puerto del emisor, además del
mensaje, permitiendo a los receptores enviar
una respuesta.

115
Sockets UDP
• En el caso de Java, proporciona tres clases para
dar soporte a la comunicación por medio de
datagramas UDP (import java.net.*;)
– DatagramSocket
– DatagramPacket
– MulticastSocket

116
DatagramSocket
• Maneja sockets para enviar y recibir datagramas UDP y
proporciona tres constructores:
1. DatagramSocket(): constructor sin argumentos que
permite que el sistema elija un puerto entre los que
estén libres y selecciona una de las direcciones locales.
2. DatagramSocket(int port): constructor que toma un
número de puerto como argumento; es apropiado para
los procesos que necesitan un número de puerto
(servicios).
3. DatagramSocket(int port, InetAddress laddr):
constructor que toma como argumentos el número de
puerto y una determinada dirección local.
117
DatagramSocket
La clase DatagramSocket proporciona varios métodos, los
más utilizados son:
• Send(DatagramPacket p) y receive(DatagramPacket p):
transmiten datagramas entre un par de conectores.
– El argumento de send es una instncia de DatagramPacket
conteniendo el mensaje y el destino.
– El argumento de receive es un DatagramPacket vacío en el que
se coloca: el mensaje, su longitud y su origen
• setSoTimeout(int timeout): permite establecer un tiempo
de espera límite
– Cuando se fija un límite, el método receive se bloquea y luego
lanza una excepción.

118
DatagramSocket
• Connect(InetAddress address, int port): se utiliza para
conectarse a un puerto remoto y a una dirección de
Internet específicos, en cuyo caso el conector sólo podrá
enviar y recibir mensajes de esa dirección.

119
Sockets
Nivel de
aplicación
Interfaz de sockets

Flujo (SOCK_STREAM) Protocolo TCP Nivel de


• Tipo transporte
Datagrama (SOCK_DGRAM) Protocolo UDP (TCP, UDP)
Nivel de red
(IP)
Nivel físico

• Dominio AF_INET Comunicación usando protocolos


TCP/IP

120
Sockets orientados a conexión no
bloqueantes
• Operaciones de entrada/salida son por lo general bloqueantes
y esto también ocurre cuando se utilizan con sockets.

• Cuando se crea un socket por medio de la llamada socket() el


kernel lo establece como bloqueante.

SOCKETS ORIENTADOS A CONEXIÓN NO BLOQUEANTES


Proceso bloqueante à El proceso pasa al
estado dormido, esperando que se
satisfaga alguna condición que permita
que se complete la operación.

121
Sockets orientados a conexión no
bloqueantes
También implica cundo se realizan algunas operaciones o llamadas sobre
un socket:

• Operaciones de salida (write(),


send(), sendto, connect(), …) • Operaciones de entrada
(read, recv, recvfrom, …)
Ej. Sobre un socket de flujo
Ej. Sobre un socket de flujo
• El kernel copia los datos del
buffer de la aplicación en el • y no hay datos

SOCKETS ORIENTADOS A CONEXIÓN NO BLOQUEANTES


buffer de envío del socket disponibles en el buffer
de recepción del socket,
• si no queda espacio en
este buffer, el proceso se
el proceso pasa a estado
bloquea hasta que haya dormido hasta que
suficiente espacio. lleguen datos.

122
Ejemplo

Aplicación Aplicación

Proceso Proceso
Cliente Servidor

SOCKETS ORIENTADOS A CONEXIÓN NO BLOQUEANTES


123
Ejemplo

Aplicación Aplicación

Proceso Proceso
Cliente Servidor

SOCKETS ORIENTADOS A CONEXIÓN NO BLOQUEANTES


124
Ejemplo

Aplicación Aplicación

recv()

Proceso Proceso
Cliente Servidor

SOCKETS ORIENTADOS A CONEXIÓN NO BLOQUEANTES


125
Ejemplo

Aplicación Aplicación

recv()

Proceso Proceso
Cliente Servidor

SOCKETS ORIENTADOS A CONEXIÓN NO BLOQUEANTES


126
Ejemplo

Aplicación Aplicación

recv()

Proceso Proceso
Cliente Servidor

SOCKETS ORIENTADOS A CONEXIÓN NO BLOQUEANTES


send()

127
Ejemplo

Aplicación Aplicación

recv()

Proceso Proceso
Cliente Servidor

SOCKETS ORIENTADOS A CONEXIÓN NO BLOQUEANTES


send()

send() recv()

128
Ejemplo

Aplicación Aplicación

recv()

Proceso Proceso
Cliente Servidor

SOCKETS ORIENTADOS A CONEXIÓN NO BLOQUEANTES


send()

send() recv()

129
Ejemplo

Aplicación Aplicación

recv()

Proceso Proceso
Cliente Servidor

SOCKETS ORIENTADOS A CONEXIÓN NO BLOQUEANTES


send()

send() recv()

130
Ejemplo

Aplicación Aplicación

No
bloqueante

recv()

Proceso Proceso
Cliente Servidor

SOCKETS ORIENTADOS A CONEXIÓN NO BLOQUEANTES


send()

send() recv()

131
¿Cómo establecer un Socket orientado a
conexión como no bloqueante?
Nota:
Es recomendable emplear algún mecanismo que nos permita realizar
estas funciones de forma no bloqueante y así poder realizar otras tareas
en vez de esperar hasta que los datos estén disponibles.

Beneficios:
• «interrogar» al socket por su
Mecanismos :
información.

SOCKETS ORIENTADOS A CONEXIÓN NO BLOQUEANTES


• fcntl()
• Si intentas leer de un socket no
bloqueante y no hay datos • select()
disponibles • Polling
• devolverá un -1 y asignará a • Asíncronos
errno el valor
EWOULDBLOCK
132
¿cómo establecer un Socket orientado a
conexión como no bloqueante?
Ventajas de sockets bloqueantes y no bloqueantes
Bloqueantes No bloqueantes:
• Permiten esperar eventos de • Permiten que un proceso (ej.
entrada salida fácilmente sin servidor ) atienda a múltiples
ocupar tiempo de CPU. clientes
Desventaja • Las funciones de entrada y
salida que no pueden realizar
• son más lentos que los no
su tarea por falta de datos
bloqueantes
retornan inmediatamente y

SOCKETS ORIENTADOS A CONEXIÓN NO BLOQUEANTES


devuelven un código de error.
• Permiten la combinación de
sockets con multi-hilos.

133
¿cómo establecer un Socket orientado a
conexión como no bloqueante?
En C, se necesita elegir entre BSD modo O_NONBLOCK o el casi idéntico Posix
modo O_NDELAY
Eso se hace después de crear el socket, pero antes de usarlo.

• La diferencia más importante es que send(), recv(), connect() y


accept() puede volver sin haber hecho nada.

SOCKETS ORIENTADOS A CONEXIÓN NO BLOQUEANTES


Hay varias alternativas
Puede comprobar el valor de retorno y el código de error por lo que su
aplicación pronto será grande, pesada y llena de errores.

134
Función fcntl()
• Es un acrónimo de ‘File Control’
• Permite llevar a cabo distintas operaciones de control sobre
descriptores
• La sintaxis es la siguiente:

Argumentos que necesita el

SOCKETS ORIENTADOS A CONEXIÓN NO BLOQUEANTES


Descriptor del socket sobre
comando, para establecer el
el cual se va a realizar alguna
socket como no bloqueante será
operación
O_NONBLOCK
Determina el comando que se va a aplicar, para este
caso se usará el comando F_SETFL, el cual establece
los flag del descriptor al valor especificado en arg.
135
Función fcntl()
• Cada descriptor tiene un conjunto de flags que se obtiene utilizando la
orden (parámetro cmd) F_GETFL y que se obtienen utilizando la orden
F_SETFL.
• Del conjunto de flags que puede manipular fcntl, los dos flags que afectan al
comportamiento de los sockets son los siguientes:
O_NONBLOCK E/S no bloqueante.
O_ASYNC E/S guiada por señales (signal-drive I/O)

Si nos centramos en la programación de aplicaciones en redes la función fcntl nos

SOCKETS ORIENTADOS A CONEXIÓN NO BLOQUEANTES


permite hacer lo siguiente:
E/S dirigida mediante señales: Si activamos el flag de estado O_ASYNC utilizando
F_SETFL conseguimos que se genere la señal SIGIO cuando se modifica el estado
de un socket.
Entrada/Salida no bloqueante: Si activamos el flag O_NONBLOCK (utilizando una
vez más F_SETFL) conseguimos hacer no-bloqueante un socket.

136
Función fcntl()

Desventajas:
• Está en espera activa
• Consume tiempo innecesario de CPU ya que no realiza ninguna
operación

SOCKETS ORIENTADOS A CONEXIÓN NO BLOQUEANTES


137
Función select()

Imagine la siguiente situación:

• Usted es un servidor y desea escuchar las conexiones entrantes, así


como mantener la lectura de las conexiones que ya tiene.

SOCKETS ORIENTADOS A CONEXIÓN NO BLOQUEANTES


138
Función select()

Imagine la siguiente situación:

• Usted es un servidor y desea escuchar las conexiones entrantes, así


como mantener la lectura de las conexiones que ya tiene.
• No hay problema, ustedes dicen, sólo un accept() y un par de recv()…
No es tan fácil!

SOCKETS ORIENTADOS A CONEXIÓN NO BLOQUEANTES


139
Función select()

Imagine la siguiente situación:

• Usted es un servidor y desea escuchar las conexiones entrantes, así


como mantener la lectura de las conexiones que ya tiene.
• No hay problema, ustedes dicen, sólo un accept() y un par de recv()…
No tan rápido!
• ¿Qué pasa si usted está bloqueado en un una llamada accept()?
¿Cómo vas a hacer un recv() de datos al mismo tiempo?

SOCKETS ORIENTADOS A CONEXIÓN NO BLOQUEANTES


140
Función select()

Imagine la siguiente situación:

• Usted es un servidor y desea escuchar las conexiones entrantes, así


como mantener la lectura de las conexiones que ya tiene.
• No hay problema, ustedes dicen, sólo un accept() y un par de recv()…
No tan rápido!
• ¿Qué pasa si usted está bloqueado en un una llamada accept()?
¿Cómo vas a hacer un recv() de datos al mismo tiempo?

SOCKETS ORIENTADOS A CONEXIÓN NO BLOQUEANTES


• à"Usar sockets no bloqueantes“? De ninguna manera! Ocupar
toda la CPU. ¿Entonces que?

141
Función select()

• Select() le da el poder de controlar varios sockets al mismo tiempo.


Podrás saber cuáles sockets están listos para la lectura, cuáles están
listos para la escritura, y qué sockets han planteado excepciones, si
realmente quieres saber eso.

Desventajas:

SOCKETS ORIENTADOS A CONEXIÓN NO BLOQUEANTES


• Aunque es una función muy portable, es uno de los métodos más
lentos para la vigilancia de sockets.

142
Función select()
• La sintaxis es la siguiente

1
2
3
4

Se proveen 4 macros para manejo del conjunto de descriptores:

SOCKETS ORIENTADOS A CONEXIÓN NO BLOQUEANTES


1 • Agrega un descriptor a un conjunto
2 • Borra un descriptor de un conjunto
3 • Verifica si un descriptor está dentro de un conjunto
4 • Limpia un conjunto de descriptores
143
Función select()

Los macros se utilizan luego del retorno de select()


para verificar cual descriptor
cambio su estado.

Timeval

SOCKETS ORIENTADOS A CONEXIÓN NO BLOQUEANTES


• Permite monitorear un conjunto de descriptores de sockets
• Nos avisa cuales tienen datos para:
– Leer
– Escribir
– Excepción

144
Mecanismos Polling

• Tarea: Mecanismos Polling


• Cuáles son
• En qué consisten
• Ventajas y desventajas

145

También podría gustarte