Creo que este post puede ser muy interesante y además un buen ejercicio para recordar las capas del modelo TCP/IP. Surge de una necesidad de gestionar a nivel de bit paquetes de red: identificar y parsear cabeceras de las capas L3 y L4 (red y transporte). Esto hecho en C++ desde un host Linux usando la API de sockets estándar pero a un nivel más bajo de lo habitual.
Mi intención es reflejar con claridad las diferencias entre distintos tipos de sockets que podemos crear y qué aporta cada uno, para poder elegir con criterio según las necesidades de cada quien. Primero repasaremos conceptualmente dos o tres tipos de sockets y el nivel de la pila en el que trabajan; después lo aterrizaremos con ejemplos de código en C++ y algún diagrama sencillo para entender exactamente qué bytes llegan a nuestro recvfrom() en cada escenario.
Configurando un socket para recibir datagramas UDP en un puerto concreto
Una necesidad my común como la de recibir datagramas UDP en un puerto concreto puede llevarnos a crear sockets como:
#include <sys/socket.h>
int s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);Donde lo importante está en i) AF_INET: especificando que la comunicación usará direcciones IPv4, en ii) SOCK_DGRAM: especificando que las comunicaciones estarán basadas en datagramas, y en iii) IPPROTO_UDP: que dice al kernel que solo nos interesan datagramas UDP. Se definien así parámetros asociados al direccionamiento IP (capa de red) y al tipo de transporte basado en datagramas. Opcionalmente, también podríamos bindear el socket a un puerto fijo en el que recibir los datagramas: