Saltar al contenido

Creación y envío de paquetes de datos en C/C++

Este escrito ha sido probado por expertos para asegurar la veracidad de nuestra esta reseña.

Solución:

Supongamos que su programa ya está organizado para tener el encabezado en uno struct y los datos en otro struct. Por ejemplo, podría tener estas estructuras de datos:

#include 
struct header 
    uint16_t f1;
    uint16_t f2;
    uint32_t f3;
;
struct data 
    uint16_t pf1;
    uint64_t pf2;
;

Llamemos a esta organización “formato de host”. Realmente no me importa cuál es el formato de host, siempre que sea útil para el resto de su programa. Llamemos al formato que pasarás al send() llamar “formato de red”. (Elegí estos nombres para que coincidieran con el htons (host-a-red-corto) y htonl (host-to-network-long) nombres.)

Aquí hay algunas funciones de conversión que podemos encontrar útiles. Cada uno de estos convierte sus estructuras de formato de host en un búfer de formato de red.

#include 
#include 
void htonHeader(struct header h, char buffer[8]) 
    uint16_t u16;
    uint32_t u32;
    u16 = htons(h.f1);
    memcpy(buffer+0, &u16, 2);
    u16 = htons(h.f2);
    memcpy(buffer+2, &u16, 2);
    u32 = htonl(h.f3);
    memcpy(buffer+4, &u32, 4);

void htonData(struct data d, char buffer[10]) 
    uint16_t u16;
    uint32_t u32;
    u16 = htons(d.pf1);
    memcpy(buffer+0, &u16, 2);
    u32 = htonl(d.pf2>>32);
    memcpy(buffer+2, &u32, 4);
    u32 = htonl(d.pf2);
    memcpy(buffer+6, u32, 4);

void htonHeaderData(struct header h, struct data d, char buffer[18]) 
    htonHeader(h, buffer+0);
    htonData(d, buffer+8);

Para enviar sus datos, haga esto:

...
char buffer[18];
htonHeaderData(myPacketHeader, myPacketData, buffer);
send(sockfd, buffer, 18, 0);
...

De nuevo, no tienes que usar el header y data estructuras que definí. Simplemente use lo que su programa necesite. los key es que tiene una función de conversión que escribe todos los datos, en compensaciones bien definidas, en un orden de bytes bien definido, en un búfer, y que pasa ese búfer a la función send().

En el otro lado de la conexión de red, necesitará un programa para interpretar los datos que recibe. En ese lado, debe escribir las funciones correspondientes (ntohHeader, etc.). Esas funciones serán memcpy los bits de un búfer y en una variable local, que puede pasar a ntohs o ntohl. Dejaré esas funciones para que las escribas.

Bueno, normalmente parecería que está preparando esa estructura de paquete en un búfer de memoria (haciendo llamadas juiciosas al htonl familia de funciones).

Si entonces usaría el send, sendto, sendmsg o write funciones, con suerte con mucho cuidado con la longitud del búfer y un buen manejo/informe de errores.

(O una de las API de Win32 para el envío, si esa es la plataforma de destino).

Encontrará una buena presentación sobre todo esto en la Guía de programación de redes de Beej.

Específicamente para la parte de empaquetado de bytes (con consideración endian), mire el tema de serialización. (Hay mucho más detalle en esa sección que lo que necesita para los tipos de datos enteros de tamaño fijo simple.

El código se vería diferente dependiendo de la biblioteca de red del sistema operativo (*nix usa sockets Berkeley, Windows usa Winsock, etc.). Sin embargo, puede crear una estructura que contenga todos los datos que desea enviar en un paquete, por ejemplo,

typedef struct

    short field1;
    short field2;
    int field3;
 HeaderStruct;

typedef struct

    short field1;
    long long field2;
 PacketDataStruct;

asumiendo un tamaño int de 32 bits.

Editar:

Como alguien me recordó amablemente en los comentarios, no se olvide de convertir hacia y desde Network Order. Las bibliotecas de redes tendrán funciones para ayudar con esto, como ntohs, nothl, htonsy htonl.

Sección de Reseñas y Valoraciones

Recuerda que puedes dar recomendación a este escrito si te fue útil.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *