Está en la página 1de 16

Instituto Politécnico Nacional

Unidad Profesional Interdisciplinaria


en Ingeniería y Tecnologías
Avanzadas

Ingeniería Telemática

Programación Avanzada

Alumnos

Barrera Martínez Juan Santiago


Nava Okamoto Luis Kenjiro

Grupo: 2TV3

Profesora: Sánchez Nájera Susana

“Sockets”

Fecha de entrega: 11/11/19


Los sockets no son más que puntos o mecanismos de comunicación entre
procesos que permiten que un proceso hable (emita o reciba información) con otro
proceso incluso estando estos procesos en distintas máquinas.
Esta característica de interconectividad entre máquinas hace que el concepto de
socket nos sirva de gran utilidad. Esta interfaz de comunicaciones es una de las
distribuciones de Berkeley al sistema UNIX, implementándose las utilidades de
interconectividad de este Sistema Operativo (rlogin, telnet, ftp, ...) usando sockets.
Un socket no es más que un "canal de comunicación" entre dos programas que
corren sobre ordenadores distintos o incluso en el mismo ordenador.
La forma de referenciar un socket por los procesos implicados es mediante un
descriptor del mismo tipo que el utilizado para referenciar ficheros. Debido a esta
característica, se podrá realizar redirecciones de los archivos de E/S estándar
(descriptores 0,1 y 2) a los sockets y así combinar entre ellos aplicaciones de la
red. Todo nuevo proceso creado heredará, por tanto, los descriptores de sockets
de su padre.
La comunicación entre procesos a través de sockets se basa en la filosofía
CLIENTE-SERVIDOR: un proceso en esta comunicación actuará de proceso
servidor creando un socket cuyo nombre conocerá el proceso cliente, el cual podrá
"hablar" con el proceso servidor a través de la conexión con dicho socket
nombrado.
El proceso crea un socket sin nombre cuyo valor de vuelta es un descriptor sobre
el que se leerá o escribirá, permitiéndose una comunicación bidireccional,
característica propia de los sockets y que lo diferencia de los pipes, o canales de
comunicación unidireccional entre procesos de una misma máquina. El
mecanismo de comunicación vía sockets tiene los siguientes pasos:

1. El proceso servidor crea un socket con nombre y espera la conexión


2. El proceso cliente crea un socket sin nombre
3. El proceso cliente realiza una petición de conexión al socket servidor
4. El cliente realiza la conexión a través de su socket mientras el proceso
servidor mantiene el socket servidor original con nombre

Es muy común en este tipo de comunicación lanzar un proceso hijo, una vez
realizada la conexión, que se ocupe del intercambio de información con el proceso
cliente mientras el proceso padre servidor sigue aceptando conexiones. Para
eliminar esta característica se cerrará el descriptor del socket servidor con nombre
en cuanto realice una conexión con un proceso socket cliente. Todo socket viene
definido por 3 características fundamentales:

1. El tipo del socket, que indica la naturaleza del mismo, el tipo de


comunicación que puede generarse entre los sockets.
2. El dominio del socket especifica el conjunto de sockets que pueden
establecer una comunicación con el mismo.
3. El protocolo que va a utilizar

Dominio de un Socket
Indica el formato de las direcciones que podrán tomar los sockets y los protocolos
que soportarán dichos sockets. La estructura genérica es:
struct sockaddr {
u__short sa__family; /* familia */
char sa__data[14]; /* dirección */
};
I. AF_UNIX: Sockets internos de UNIX (Sockets del sistema de archivos).

El cliente y el servidor deben estar en la misma máquina. Debe incluirse el


fichero cabecera /usr/include/sys/un.h. La estructura de una dirección en
este dominio es:
struct sockaddr__un {
short sun__family; /* en este caso AF_UNIX */
char sun__data[108]; /* dirección */
};

II. AF_INET: Protocolos de internet ARPA (Sockets de redes de UNIX).

El cliente y el servidor pueden estar en cualquier máquina de la red Internet.


Deben incluirse los ficheros cabecera /usr/include/netinet/in.h,
/usr/include/arpa/inet.h, /usr/include/netdb.h. La estructura de una dirección
en este dominio es:

struct in__addr {
u__long s__addr;
};

struct sockaddr__in {
short sin_family; /* en este caso AF_INET */
u__short sin_port; /* numero del puerto */
struct in__addr sin__addr; /* direcc Internet */
char sin_zero[8]; /* campo de 8 ceros */ };
III. AF_ISO: Protocolos estándar ISO.
IV. AF_NS: Protocolos de redes Xerox

Protocolo
Se usa donde el mecanismo de transporte permite más de un protocolo a ser
usado. En las redes de UNIX y en los sockets de sistema de archivos no
necesitamos seleccionar otro protocolo diferente al default.

Tipos
SOCK_STREAM: Para flujo
 Son implementados en el dominio AF_INET por conexiones TCP/IP.
 Son el tipo usual en el dominio AF_UNIX.

SOCK_DGRAM : Para datagramas


 No establecen ni mantienen una conexión.
 También existe un límite en el tamaño del datagrama que se puede enviar.
 Se transmite como un solo mensaje en la red que se puede perder,
duplicar o llegar fuera de secuencia.

Un socket queda definido por una dirección IP, un protocolo y un número de


puerto. En el caso concreto de TCP-IP, un socket se define por una dupla Origen –
Destino. Tanto el origen como el destino vienen indicados por un par (ip, puerto).
Existen dos tipos los no orientados a la conexión donde el programa de aplicación
da la fiabilidad y los orientados a conexión don hay un circuito virtual.
Propiedades:
 Fiabilidad de la Transmisión. No se pierden los datos transmitidos.
 Conservación del Orden de los Datos. Los datos llegan en el orden en que
se emitieron.
 No Duplicación de los Datos. El Dato sólo llega una vez.
 Comunicación en modo conectado. La conexión está establecida antes de
iniciar la comunicación. De este modo, la emisión desde un extremo va
destinada al otro (implícitamente).
 Conservación de los límites de los mensajes. Los límites de mensajes
emitidos pueden encontrarse o conocerse en el destino.
 Envío de Mensajes “urgentes”. Permite el envío de datos fuera de flujo o
fuera de banda. Al enviar datos fuera del flujo normal, son accesibles de
inmediato.

El protocolo UDP es un protocolo no orientado a la conexión, sin garantía de


entrega. En ningún caso se garantiza que llegue o que lleguen todos los mensajes
en el mismo orden que se mandaron. Esto lo hace adecuado para el envío de
mensajes frecuentes, pero no demasiado importantes como por ejemplo un
streaming de audio.

Sockets no orientados a conexión


 Es el llamado protocolo UDP.
 No es necesario que los programas se conecten.
 Cualquiera de ellos puede transmitir datos en cualquier momento,
independientemente de que el otro programa esté "escuchando" o no.
 Garantiza que los datos que lleguen son correctos, pero no garantiza que
lleguen todos.
 Se utiliza cuando es muy importante que el programa no se quede
bloqueado.
 No importa que se pierdan datos.

Filosofía cliente-servidor
CLIENTE: Es un ordenador que solicita al servidor que ejecute algún tipo de tarea.
SERVIDOR: Es un ordenador que está conectado a una red y que ofrece sus
servicios a cualquier nodo que los solicite. El servidor puede atender a varios
clientes al mismo tiempo.
Resumiendo, esta filosofía describe un sistema en el que un equipo llamado
cliente solicita a otro equipo llamado servidor que ejecute una tarea específica.

La arquitectura cliente-servidor es un modelo de diseño de software en el que las


tareas se reparten entre los proveedores de recursos o servicios, llamados
servidores, y los demandantes, llamados clientes. Un cliente realiza peticiones a
otro programa, el servidor, quien le da respuesta. Esta idea también se puede
aplicar a programas que se ejecutan sobre una sola computadora, aunque es más
ventajosa en un sistema operativo multiusuario distribuido a través de una red de
computadoras. Algunos ejemplos de aplicaciones computacionales que usen el
modelo cliente-servidor son el Correo electrónico, un Servidor de impresión y la
World Wide Web.
En esta arquitectura la capacidad de proceso está repartida entre los clientes y los
servidores, aunque son más importantes las ventajas de tipo organizativo debidas
a la centralización de la gestión de la información y la separación de
responsabilidades, lo que facilita y clarifica el diseño del sistema.
La separación entre cliente y servidor es una separación de tipo lógico, donde el
servidor no se ejecuta necesariamente sobre una sola máquina ni es
necesariamente un solo programa. Los tipos específicos de servidores incluyen los
servidores web, los servidores de archivo, los servidores del correo, etc. Mientras
que sus propósitos varían de unos servicios a otros, la arquitectura básica seguirá
siendo la misma.
La red cliente-servidor es una red de comunicaciones en la cual los clientes están
conectados a un servidor, en el que se centralizan los diversos recursos y
aplicaciones con que se cuenta; y que los pone a disposición de los clientes cada
vez que estos son solicitados. Esto significa que todas las gestiones que se
realizan se concentran en el servidor, de manera que en él se disponen los
requerimientos provenientes de los clientes que tienen prioridad, los archivos que
son de uso público y los que son de uso restringido, los archivos que son de sólo
lectura y los que, por el contrario, pueden ser modificados, etc. Este tipo de red
puede utilizarse conjuntamente en caso de que se esté utilizando en una red
mixta.

Cliente:
 Es quien inicia solicitudes o peticiones, tienen por tanto un papel activo en
la comunicación (dispositivo maestro o amo).
 Espera y recibe las respuestas del servidor.
 Por lo general, puede conectarse a varios servidores a la vez.
 Normalmente interactúa directamente con los usuarios finales mediante una
interfaz gráfica de usuario.
int socket ( int dominio, int tipo, int protocolo)
Crea un socket sin nombre de un dominio, tipo y protocolo específico
• dominio : AF_INET, AF_UNIX
• tipo : SOCK__DGRAM, SOCK__STREAM
• protocolo : 0 ( protocolo por defecto )
int connect ( int dfCliente, struct sockaddr* direccServer, intlongDirecc)
Intenta conectar con un socket servidor cuya dirección se encuentra incluida en la
estructura apuntada por direccServer. El descriptor dfCliente se utilizará para
comunicar con el socket servidor. El tipo de estructura dependerá del dominio en
que nos encontremos.

Servidor:
 Al iniciarse esperan a que lleguen las solicitudes de los clientes,
desempeñan entonces un papel pasivo en la comunicación (dispositivo
esclavo).
 Tras la recepción de una solicitud, la procesan y luego envían la respuesta
al cliente.
 Por lo general, acepta las conexiones de un gran número de clientes (en
ciertos casos el número máximo de peticiones puede estar limitado).
int socket ( int dominio, int tipo, int protocolo):
• crea un socket sin nombre de un dominio, tipo y protocolo específico
• dominio : AF_INET, AF_UNIX
• tipo : SOCK__DGRAM, SOCK__STREAM
• protocolo : 0 ( protocolo por defecto )
int bind ( int dfServer, struct sockaddr* direccServer, int longDirecc)
Nombra un socket: asocia el socket no nombrado de descriptor dfServer con la
dirección del socket almacenado en direccServer. La dirección depende de si
estamos en un dominio AF_UNIX
o AF_INET.
int listen ( int dfServer, int longCola)
Especifica el máximo número de peticiones de conexión pendientes.
int accept ( int dfServer, struct sockaddr* direccCliente, int* longDirecc)
Escucha al socket nombrado “servidor dfServer” y espera hasta que se reciba
la petición de la conexión de un cliente.Al ocurrir esta incidencia, crea un
socket sin nombre con las mismas características que el socket servidor
original, lo conecta al socket cliente y devuelve un descriptor de fichero que
puede ser utilizado para la comunicación con el cliente.
Avisar al sistema de que comience a atender dicha conexión de red.
Se consigue mediante la función listen(). A partir de este momento el sistema
operativo anota r á la conexión de cualquier cliente para pasárnosla cuando se
lo pidamos.
Si llegan clientes más rápido de lo que somos capaces de atenderlos, el
sistema operativo hace una "cola" con ellos y nos los ir á pasando según
vayamos pidiéndolo.
Pedir y aceptar las conexiones de clientes al sistema operativo.
Para ello hacemos una llamada a la función accept(). Esta función le indica al
sistema operativo que nos d é al siguiente cliente de la cola. Si no hay clientes
se quedar á bloqueada hasta que algún cliente se conecte.
En la arquitectura C/S sus características generales son:
 El Cliente y el Servidor pueden actuar como una sola entidad y también
pueden actuar como entidades separadas, realizando actividades o tareas
independientes.
 Las funciones de Cliente y Servidor pueden estar en plataformas
separadas, o en la misma plataforma.
 Cada plataforma puede ser escalable independientemente. Los cambios
realizados en las plataformas de los Clientes o de los Servidores, ya sean
por actualización o por reemplazo tecnológico, se realizan de una manera
transparente para el usuario final.
 La interrelación entre el hardware y el software están basados en una
infraestructura poderosa, de tal forma que el acceso a los recursos de la red
no muestra la complejidad de los diferentes tipos de formatos de datos y de
los protocolos.
 Su representación típica es un centro de trabajo (PC), en donde el usuario
dispone de sus propias aplicaciones de oficina y sus propias bases de
datos, sin dependencia directa del sistema central de información de la
organización.
Señales

Las señales son interrupciones de software. Permiten el manejo de eventos


asíncronos. Una señal (del inglés signal) es una forma limitada de comunicación
entre procesos empleada en Unix y otros sistemas operativos compatibles con
POSIX. En esencia es una notificación asíncrona enviada a un proceso para
informarle de un evento. Cuando se le manda una señal a un proceso, el sistema
operativo modifica su ejecución normal. Si se había establecido anteriormente un
procedimiento (handler) para tratar esa señal se ejecuta éste, si no se estableció
nada previamente se ejecuta la acción por defecto para esa señal.
Los manipuladores de señales se establecen mediante la llamada al sistema
signal(). Si hay un manipulador de señal para una señal dada se invoca y, si no lo
hay, se usa el manipulador por defecto. El proceso puede especificar también dos
comportamientos por defecto sin necesidad de crear un manipulador: ignorar la
señal (SIG_IGN) y usar el manipulador por defecto (SIG_DFL). Hay dos señales
que no pueden ser interceptadas ni manipuladas: SIGKILL y SIGSTOP.
La manipulación de señales es vulnerable a que se produzca una condición de
carrera, pues las señales son asíncronas y puede ocurrir que llegue otra señal
(incluso del mismo tipo) al proceso mientras transcurre la ejecución de la función
que manipula la señal. Puede usarse la función sigprocmask para desbloquear la
entrega de señales.Las señales pueden interrumpir una llamada al sistema en
proceso, dejando en manos de la aplicación la gestión del PCLSRing.
El archivo < signum.h > contiene la definición de todas las señales. La ubicación
definitiva de las señales depende del sistema operativo de su máquina.
Generalmente se puede llegar a él vía /usr/include/signal.h. En Aragorn este
archivo está en: /usr/include/bits/signum.h
Numerosas condiciones pueden generar señales. Entre ellas:
 Presionando la tecla DELETE (también control-C)
 Excepción de hardware: División por cero, referencia de memoria invalida
(SIGSEGV)
 Kill: existe como función y como comando. El procesador que envía debe
pertenecer al mismo usuario del que recibe o ser superusuario.
 Condiciones de software. Por ejemplo: SIGALRM generada por a la alarma
del reloj cuando expira. SIGPIPE: cuando se escribe en una "pipe" que ha
terminado por el lado lector.
Hay tres cosas que un programa puede solicitar al kernel como acción cuando
llegue una señal:
I. Ignorar la señal. Sin embargo, hay dos señales que no pueden ser
ignoradas: SIGKILL y SIGSTOP.
II. Capturar la señal. El kernel llama una función dentro del programa cuando
la señal ocurre.
III. Permitir que se aplique la acción por defecto. Esta puede ser: terminal el
proceso, terminar con un core dump, parar el proceso, o ignorar la señal.

Algunas señales:
 SIGALRM: generada cuando el timer asociado a la función alarm expira.
También cuando el timer de intervalo es configurado (setitimer)
 SIGCHLD: Cuando un proceso termina o para, el proceso envía esta señal
a su padre. Por defecto esta señal es ignorada. Normalmente el proceso
padre invoca la función wait para obtener el estatus de término del proceso
hijo. Se evita así la creación de procesos "zombies".
 SIGCONT: es enviada para reanudar un proceso que ha sido parado
(suspendido) con SIGSTOP.
 SIGINT: generada con DELETE o Control-C
 SIGKILL: Permite terminar un proceso.
 SIGTSTP: generada cuando presionamos Control-Z. Puede ser ignorada.
 SIGSTOP: similar a SIGTSTP pero no puede ser ignorada o capturada.
 SIGUSR1: Es una señal definida por el usuario para ser usada en
programas de aplicación.
 SIGUSR2: Otra como la anterior.

Función signal
#include <signal.h>
void (*signal (int signo, void (*func) (int)))(int);

Este prototipo es equivalente a:


typedef void Sigfunc(int);
Sigfunc * signal (int signo, Sigfunc *);

signo: es el nombre de la señal.


func: puede ser la constante SIG_IGN para ignorar la señal, SIG_DFL para usar la
acción por defecto, o puede ser una función definida por el programa. Esta función
es conocida como el manejador de la señal (signal handler). El valor retornado es
un puntero al manejador previamente instalado para esa señal.

Interrupción de llamados al sistema


La semántica de la mayoría de los sistemas operativos actuales emergentes de
UNIX cambió el año 2001 respecto a la acción de una llamada al sistema "lenta"
ante la llegada de una señal.
En versiones previas, al arribo de una señal a un proceso bloqueado en una
llamado al sistema "lento", el llamado al sistema retorna(ba) un error y el valor de
errno es EINTR.
Típico código para atender esta situación era:
again:
if ( (n=read(fd, buff, BUFFSIZE)) < 0) {
if(errno == EINTR)
goto again;
/* manejo de otros errores */ }
Esta situación no es crítica en las nuevas versiones del SO por cuanto las
operaciones como read no son interrumpida producto de la llegada de una señal.
La señal sí es procesada igualmente.

Funciones kill y raise


Kill envía una señal a un proceso o a un grupo de procesos.
Raise permite enviar señales al mismo proceso (hacia uno mismo).
#include <sys/types.h>
#include <signal.h>
int kill (pid_t pid, int signo);

int raise(int signo);

Este último es como kill( getpid(), signo);

Funciones alarm y pause


La función alarm permite especificar un timer que expire en un tiempo dado.
La función pause suspemde al proceso llamador hasta que llegue una señal.

#include <unistd.h>
unsigned int alarm(unsigned int seconds);
En nuevas versiones de sistema operativo también se puede usar
unsigned int ualarm(unsigned int microseconds);
int pause(void); /* retorna -1 con errno en EINTR */

El control del tiempo no es exacto por la incertidumbre del kernel, carga del
sistema, etc. La alarma se puede cancelar con seconds=0 en el argumento. El
valor retornado es lo que falta para que el reloj expire.

Ejemplos:
Bibliografías:
 http://es.tldp.org/Universitarios/seminario-2-sockets.html
 http://sopa.dis.ulpgc.es/ii-dso/leclinux/ipc/sockets/sockets.pdf
 http://www.starlinux.net/staticpages/index.php?page=20020720164837437
 http://profesores.elo.utfsm.cl/~agv/elo330/2s08/lectures/signals.html
 http://sopa.dis.ulpgc.es/progsis/material-didactico-
teorico/tema4_1transporpagina.pdf

También podría gustarte