Docsity
Docsity

Prepara tus exámenes
Prepara tus exámenes

Prepara tus exámenes y mejora tus resultados gracias a la gran cantidad de recursos disponibles en Docsity


Consigue puntos base para descargar
Consigue puntos base para descargar

Gana puntos ayudando a otros estudiantes o consíguelos activando un Plan Premium


Orientación Universidad
Orientación Universidad


Explicacion de SOCKETs, Diapositivas de Sistemas Operativos

Sockets en los sitsemas operativos

Tipo: Diapositivas

2020/2021

Subido el 06/06/2023

alvaro-antonio-mejia-quiroz
alvaro-antonio-mejia-quiroz 🇳🇮

2 documentos

1 / 19

Toggle sidebar

Esta página no es visible en la vista previa

¡No te pierdas las partes importantes!

bg1
PROGRAMACIÓN CON SOCKETS
Pág. 1
PROGRAMACIÓN CON SOCKETS
ÍNDICE
1. Introducción.
2. Estructuras y manipulación de datos.
3. API de sockets (llamadas al sistema).
4. Esquemas para servidor/cliente TCP, servidor/cliente UDP y
para servidor TCP concurrente.
pf3
pf4
pf5
pf8
pf9
pfa
pfd
pfe
pff
pf12
pf13

Vista previa parcial del texto

¡Descarga Explicacion de SOCKETs y más Diapositivas en PDF de Sistemas Operativos solo en Docsity!

PROGRAMACIÓN CON SOCKETS

Pág. 1

PROGRAMACIÓN CON SOCKETS

ÍNDICE

1. Introducción.

2. Estructuras y manipulación de datos.

3. API de sockets (llamadas al sistema).

4. Esquemas para servidor/cliente TCP, servidor/cliente UDP y

para servidor TCP concurrente.

Pág. 2

PROGRAMACIÓN CON SOCKETS

BIBLIOGRAFÍA

• Básica:

– W. R. Stevens: “Unix Network Programming”. Volume 1:

Networking APIs-Sockets and XTI. 1998 (L/S 004.451.9 UNIX

STE ).

– Capítulo 22 de D. E. Comer: “Internetworking with TCP/IP vol I”,

2 Ed. Prentice Hall, 2000.

– Beej's Guide to Network Programming

(http://www.it.uc3m.es/celeste/docencia/inf/rroo/practica/sockets

.html).

• Complementaria:

– http://www.gnu.org/software/libc/manual/html_node/Sockets.ht

ml

Pág. 3

PROGRAMACIÓN CON SOCKETS - INTRODUCCIÓN

Introducción

• TCP/IP no define el interfaz con los programas de aplicación (API).

  • Depende mucho del sistema operativo.

• El interfaz socket , de BSD UNIX, se ha convertido en el estándar

“de facto”.

  • A principios de los 80s, ARPA funda un grupo en la Universidad de

California en Berkeley para integrar TCP/IP en el sistema operativo

UNIX

  • El sistema que desarrollaron se conoce como Berkeley UNIX o BSD

UNIX.

  • Como parte del proyecto, se define un API para que las aplicaciones

puedan usar TCP/IP para comunicarse: interfaz socket.

  • Comunicación entre procesos (IPC).
  • Aparece a partir de la versión 4.1 de BSD
  • Se basa en las llamadas de E/S de UNIX.

• En el interfaz socket se basan los APIs de otros sistemas (como el

WinSock ).

Pág. 6

PROGRAMACIÓN CON SOCKETS - INTRODUCCIÓN

Comunicación entre procesos (IPC)

• Sigue una estructura parecida a la Entrada/Salida:

Crear socket

Conectar

Enviar

Recibir

Cerrar socket

Pág. 7

PROGRAMACIÓN CON SOCKETS - ESTRUCTURAS Y MANIPULACIÓN DE DATOS

Manipulación de datos: ordenación de octetos

  • Dos posibles ordenaciones de los octetos:
    • Primer octeto es el más significativo.
    • Primer octeto es el menos significativo.
  • La “ordenación de octetos de la red” sigue la primera ordenación (“ Big-

Endian ”), pero los ordenadores pueden almacenar sus datos de cualquier

de la dos formas, por lo tanto en algunos casos es preciso realizar

conversiones.

  • Todo lo que se envíe por la red debe seguir la “ordenación de la red”.
  • Métodos de conversión (#include <netinet/in.h>):
    • htons(): “ Host to Network Short ” (short de máquina a short de red).
    • htonl(): “ Host to Network Long ” (long de máquina a long de red).
    • ntohs(): “ Network to Host Short ” (short de la red a short de la máquina).
    • ntohl() :Network to Host Long ” (long de red a long de máquina).

Pág. 8

PROGRAMACIÓN CON SOCKETS - ESTRUCTURAS Y MANIPULACIÓN DE DATOS

Estructura sockaddr

• Mantiene información sobre direcciones de sockets.

• Campos:

  • sa_family: familia de direcciones (admite varios valores, en nuestro

caso AF_INET).

  • sa_data: dirección y número de puerto para el socket.

struct sockaddr { unsigned short sa_family; char sa_data[14]; };

Pág. 9

PROGRAMACIÓN CON SOCKETS - ESTRUCTURA Y MANIPULACIÓN DE DATOS

Estructura sockaddr_in

  • Mantiene información sobre direcciones de sockets (más fácil manejo que

la estructura anterior).

  • Campos:
    • sin_family: admite varios valores, en nuestro caso AF_INET.
    • sin_port: número de puerto para el socket.
    • sin_addr: dirección IP para el socket.
    • sin_zero: relleno para mantener el mismo tamaño que sockaddr (debe rellenarse a cero).
  • Notas:
    • sin_port y sin_addr deben seguir la “ordenación de octetos de la red”.
    • Es posible hacer “casting” entre estructuras sockaddr_in y sockaddr.

struct sockaddr_in { short int sin_family; unsigned short int sin_port; struct in_addr sin_addr; unsigned char sin_zero[8]; };

Pág. 12

PROGRAMACIÓN CON SOCKETS - API DE SOCKETS

API de socket: bind()

  • sockfd: descriptor del socket.
  • my_addr: es un puntero a una estructura sockaddr.
  • addrlen: longitud de la estructura anterior.
  • Resultado:
    • “-1” si se ha producido un error.

#include <sys/types.h> #include <sys/socket.h>

int bind(int sockfd, struct sockaddr *my_addr, int addrlen);

Pág. 13

PROGRAMACIÓN CON SOCKETS - API DE SOCKETS

API de socket: bind()

my_addr.sin_port = 0; /* selecciona, aleatoriamente, un puerto sin usar / my_addr.sin_addr.s_addr = htnol(INADDR_ANY); / usa mi dirección IP */

• Consideraciones sobre la elección de puerto:

  • Todos los puertos por debajo del 1024 están RESERVADOS, a menos

que seas súper-usuario.

  • Puedes usar cualquier número de puerto por encima de ese, hasta el

65535, siempre y cuando no lo esté usando ya otro programa.

• La llamada a bind se emplea en programas servidores, en

programas clientes no es necesario realizar esta llamada (se llama

a connect).

Pág. 14

PROGRAMACIÓN CON SOCKETS - API DE SOCKETS

API de socket: ejemplo de bind()

#include <string.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h>

#define MYPORT 3490

void main() { int sockfd; struct sockaddr_in my_addr;

/* Chequear si devuelve -1! / sockfd = socket(AF_INET, SOCK_STREAM, 0); my_addr.sin_family = AF_INET; / Ordenación de la máquina / my_addr.sin_port = htons(MYPORT); / Ordenación de la red / my_addr.sin_addr.s_addr = inet_addr("132.241.5.10"); / Pone a cero el resto de la estructura / memset(&(my_addr.sin_zero), '\0', 8); / Chequear si devuelve -1! */ bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)); ...

Pág. 15

PROGRAMACIÓN CON SOCKETS - API DE SOCKETS

API de socket: connect()

  • sockfd: descriptor del socket.
  • serv_addr: es un puntero a una estructura sockaddr que contiene el

puerto y la dirección IP del destino.

  • addrlen: longitud de la estructura anterior.
  • Resultado:
    • “-1” si se ha producido un error.

#include <sys/types.h> #include <sys/socket.h>

int connect(int sockfd, struct sockaddr *serv_addr, int addrlen);

Pág. 18

PROGRAMACIÓN CON SOCKETS - API DE SOCKETS

API de socket: listen()

  • sockfd: descriptor del socket.
  • backlog: número de conexiones permitidas en la cola de entrada.
  • Resultado:
    • “-1” si se ha producido un error.

#include <sys/socket.h>

int listen(int sockfd, int backlog);

Pág. 19

PROGRAMACIÓN CON SOCKETS - API DE SOCKETS

API de socket: accept()

  • sockfd: descriptor del socket.
  • addr: puntero a una estructura struct sockaddr_in local, donde se

guardará la información de la conexión entrante y con ella se puede

averiguar qué máquina se está conectando, y desde qué puerto.

  • addrlen: longitud de la estructura anterior.
  • Resultado:
    • Devuelve un descriptor de un socket conectado al cliente.
    • “-1” si se ha producido un error.
  • NOTA: se realiza en los programas servidores:
    • Sockets pasivos.
    • Quedan a la espera de recibir peticiones de conexión.

#include <sys/socket.h>

int accept(int sockfd, void *addr, int *addrlen);

Pág. 20

PROGRAMACIÓN CON SOCKETS - API DE SOCKETS

API de socket: ejemplo de accept()

#include <string.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h>

#define MYPORT 3490 /* Puerto al que se conectarán los clientes / #define BACKLOG 10 / Número de conexiones que vamos a mantener en cola */

void main(){ int sockfd, new_fd; /* Se escucha sobre sock_fd, nuevas conexiones sobre new_fd / struct sockaddr_in my_addr; / Información sobre mi dirección / struct sockaddr_in their_addr; / Información sobre la dirección remota */ int sin_size; sockfd = socket(AF_INET, SOCK_STREAM, 0);

my_addr.sin_family = AF_INET; /* Ordenación de la máquina / my_addr.sin_port = htons(MYPORT); / Ordenación de la red */ my_addr.sin_addr.s_addr = htonl(INADDR_ANY); memset(&(my_addr.sin_zero), '\0', 8); bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)); listen(sockfd, BACKLOG); sin_size = sizeof(struct sockaddr_in); new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size); …

Pág. 21

PROGRAMACIÓN CON SOCKETS - API DE SOCKETS

API de socket: send()

  • sockfd: descriptor del socket.
  • msg: puntero a los datos que se quieren enviar.
  • len: longitud de los datos en octetos.
  • flags: normalmente a 0.
  • Resultado:
    • Número de octetos enviados. (¡¡¡ Puede ser menor que len!!!)
    • “-1” si se ha producido un error.
  • Es el método de envío en sockets stream.

#include <sys/types.h> #include <sys/socket.h>

int send(int sockfd, const void *msg, int len, int flags);

Pág. 24

PROGRAMACIÓN CON SOCKETS - API DE SOCKETS

API de socket: recvfrom()

  • sockfd: descriptor del socket.
  • buf: el buffer donde se va a depositar la información leída.
  • len: longitud máxima del buffer.
  • flags: normalmente a 0.
  • from: contiene información sobre la IP y puerto de la máquina de origen.
  • fromlen: longitud de la estructura anterior.
  • Resultado:
    • Número de octetos recibidos.
    • “0” la máquina remota a cerrado la conexión.
    • “-1” si se ha producido un error.
  • Es el método de recepción en sockets datagram.
  • NOTA: si usas socket datagram pero has realizado un connect() se puede utilizar el método recv.

#include <sys/types.h> #include <sys/socket.h>

int recvfrom(int sockfd, void *buf, int len, unsigned int flags, struct sockaddr *from, int *fromlen);

Pág. 25

PROGRAMACIÓN CON SOCKETS - API DE SOCKETS

API de socket: otras llamadas

lectura/escritura

• Existen otras llamadas equivalentes:

  • int sendmsg(int sockfd, const struct msghdr *msg,

int flags)

  • int recv(int s, struct msghdr *msg, int flags)

• Se puede utilizar también los métodos de escritura y lectura de

E/S:

  • int write(socket, buffer, length)
  • int read(socket, buffer, length)

Pág. 26

PROGRAMACIÓN CON SOCKETS - API DE SOCKETS

API de socket: close()

  • sockfd: descriptor del socket.
  • Si se cierra un socket con close el otro extremo cuando intente leer o

escribir de ese socket recibirá un error. Para tener más control y realizar

por ejemplo un “half-close” es necesario emplear la llamada:

int close(sockfd);

int shutdown(int sockfd, int how);

  • sockfd: descriptor del socket.
  • how: toma uno de los siguientes valores:
    • “0” no se permite recibir más datos.
    • “1” no se permite enviar más datos.
    • “2” no se permite enviar ni recibir más datos (lo mismo que close()).

Pág. 27

PROGRAMACIÓN CON SOCKETS - API DE SOCKETS

API de socket: llamadas auxiliares

  • sockfd: descriptor del socket.
  • addr: puntero a una estructura sockaddr que guardará la información acerca del otro lado de la conexión.
  • addrlen: longitud de la estructura anterior.

#include <sys/socket.h>

int getpeername(int sockfd, struct sockaddr *addr, int *addrlen);

#include <sys/socket.h>

int getsockname(int sockfd, struct sockaddr *addr, int *addrlen);

  • sockfd: descriptor del socket.
  • addr: puntero a una estructura sockaddr que guardará la información acerca del extremo local de la conexión.
  • addrlen: longitud de la estructura anterior.

Pág. 30

PROGRAMACIÓN CON SOCKETS - API DE SOCKETS

API de socket: llamadas auxiliares

#include <netdb.h>

struct hostent *gethostbyname(const char *name);

struct hostent { char *h_name; char **h_aliases; int h_addrtype; int h_length; char **h_addr_list; }; #define h_addr h_addr_list[0]

  • h_name : nombre oficial de la máquina.
  • h_aliases : vector [ array ] terminado en NULL de nombres alternativos de máquina.
  • h_addrtype : tipo de la dirección que se devuelve; usualmente AF_INET.
  • h_length : longitud de la dirección en octetos.
  • h_addr_list : un vector terminado en cero de direcciones de red de la máquina.
  • h_addr : la primera dirección de h_addr_list.

Pág. 31

PROGRAMACIÓN CON SOCKETS - API DE SOCKETS

API de socket: llamadas auxiliares

#include <stdio.h> #include <stdlib.h> #include <errno.h> #include <netdb.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h>

int main(int argc, char *argv[]){ struct hostent *h;

if (argc != 2) { // Comprobación de errores en la línea de comandos fprintf(stderr,"usage: getip address\n"); exit(1); } if ((h=gethostbyname(argv[1])) == NULL) { // Obtener información del host herror("gethostbyname"); exit(1); } printf("Host name : %s\n", h->h_name); printf("IP Address : %s\n", inet_ntoa(*((struct in_addr *)h->h_addr))); return 0; }

Pág. 32

PROGRAMACIÓN CON SOCKETS - ESQUEMAS

Cliente TCP

1. Averiguar la dirección IP y puerto del servidor con el que desea

comunicarse.

2. Crear un socket: llamada a socket()

3. Especificar que TCP use cualquier puerto local libre.

  • Lo hace automáticamente el connect() si no se hace previamente

un bind().

4. Conectar con el servidor.

  • Esto abre la conexión TCP: llamada a connect().

5. Comunicarse con el servidor

  • Enviar y recibir por el socket (llamadas a send/recv, write/read,

6. Cerrar el socket: llamada a close().

Pág. 33

PROGRAMACIÓN CON SOCKETS - ESQUEMAS

Servidor TCP

1. Crear un socket: llamada a socket().

2. Asociarlo al puerto local “bien conocido” que ofrece ese servicio:

llamada a bind().

3. Poner el socket en modo pasivo, dispuesto a aceptar peticiones

de conexión: llamada a listen().

4. Bucle:

  • Recibir petición de cliente.
  • Atender petición (por nuevo socket): llamada a accept()
    • Enviar/recibir por socket (llamadas a send/recv, write/read, ...).
    • Cerrar nuevo socket (llamada a close()) y volver a punto 3.

5. Cerrar socket: llamada a close().

Pág. 36

PROGRAMACIÓN CON SOCKETS - ESQUEMAS

Servidor TCP concurrente

1. Crear un socket.

2. Asociarlo al puerto local “bien conocido” que ofrece ese servicio.

3. Poner el socket en modo pasivo, dispuesto a aceptar peticiones

de conexión.

4. Cuando recibe petición de cliente:

  • Crea un nuevo proceso hijo:
    • Le pasa el nuevo socket para atender esa petición.
  • Vuelve al punto 3.

5. Cerrar socket.

6. En paralelo, el proceso esclavo interactúa con el cliente.

  • Enviar/recibir por socket.
  • Cierra el socket y termina.