Enviando una estructura a través de un socket en c

Quiero enviar una estructura de datos a través de un socket en un servidor/programa tcp cliente escrito en C. Sin embargo, cuando intento imprimir los datos enviados, no imprime nada. Ya me he dado cuenta de que enviar estructuras de esta manera es una mala idea, las publicaciones que he visto no son muy útiles para encontrar una manera de hacer que esto funcione. Aquí está la estructura de datos en cuestión:

#define BUFFSIZE 1024
#define USERLEN 32
#define OPTLEN 16

struct  message{
  char option[OPTLEN];
  char user[USERLEN];
  char buff[BUFFSIZE]; 
  char target[USERLEN];
  int sockid;
};

gracias por adelantado.

1
La única parte que puede causar problemas es el sockid . Hay una pregunta sobre la frecuencia con la que su buff en realidad contendrá más de 1000 caracteres, en lugar de unos pocos; podría ser mejor enviar solo los caracteres activos para un campo tan largo, pero los otros probablemente podrían enviarse completos. Busque "serialización": ese es el proceso que necesita para enviar los datos y la "deserialización" para recibirlos.
agregado el autor Jonathan Leffler, fuente
¿Has leído esta respuesta anterior a una pregunta muy similar? ¿En qué punto eso no funciona para ti? stackoverflow.com/questions/8000851/…
agregado el autor Magnus, fuente
¿Has leído esta respuesta anterior a una pregunta muy similar? ¿En qué punto eso no funciona para ti? stackoverflow.com/questions/8000851/…
agregado el autor Magnus, fuente
Si quieres usar un protocolo binario, te sugiero protobuf de Google :)
agregado el autor geckos, fuente
Si quieres usar un protocolo binario, te sugiero protobuf de Google :)
agregado el autor geckos, fuente
simplemente conviértalo en una matriz de caracteres para serializarlo y si necesita restringirlo a charrs reales, simplemente codifique en base64
agregado el autor noone392, fuente
simplemente conviértalo en una matriz de caracteres para serializarlo y si necesita restringirlo a charrs reales, simplemente codifique en base64
agregado el autor noone392, fuente

6 Respuestas

Solo puedes escribir el mensaje en el socket:

struct message mymess;
...
write(socketfd, &mymess, sizeof(struct message));

y luego leerlo de nuevo en el lado del cliente. Eso funciona si siempre es el mismo hardware/compilador, ya que la estructura se compilará de la misma manera. Si no tiene memset() la totalidad de mymess, entonces es probable que tenga cosas sin inicializar en la escritura (). Debe ser seguro, pero puede desencadenar los controles de cordura.

Para una mensajería más confiable, necesita diseñar o adoptar un protocolo de serialización. JSON es extremadamente popular (aunque quizás no entre los programadores de C), pero hay muchos otros.

1
agregado

Solo puedes escribir el mensaje en el socket:

struct message mymess;
...
write(socketfd, &mymess, sizeof(struct message));

y luego leerlo de nuevo en el lado del cliente. Eso funciona si siempre es el mismo hardware/compilador, ya que la estructura se compilará de la misma manera. Si no tiene memset() la totalidad de mymess, entonces es probable que tenga cosas sin inicializar en la escritura (). Debe ser seguro, pero puede desencadenar los controles de cordura.

Para una mensajería más confiable, necesita diseñar o adoptar un protocolo de serialización. JSON es extremadamente popular (aunque quizás no entre los programadores de C), pero hay muchos otros.

1
agregado

Para las mismas máquinas y compiladores puedes hacer lo siguiente:

// define your structure:
#define BUFFSIZE 1024
#define USERLEN 32
#define OPTLEN 16

typedef struct message{
  char option[OPTLEN];
  char user[USERLEN];
  char buff[BUFFSIZE]; 
  char target[USERLEN];
  int sockid;
}my_message;


// now you can use it in your program

my_message m;

// initialize m
...
strcpy(m.user,"1234");
...
m.sockid = sockfd;

// send it over 

if ((nbytes = write(sockfd, &m, sizeof(my_message)) != sizeof(my_message))
{
  printf("error writing my message");
}



// read the message on the other side:
...
my_message received_message;
int size;

if( (size = recv ( sockfd, (void*)&received_message, sizeof(my_message), 0)) >= 0)
{
    //check the size
}

// It would work for same machines 32/64 bits and same compilers.

Si necesita una mejor portabilidad, intente protobuf-c , nanopb , serialización binaria binn o tpl .

0
agregado

Para las mismas máquinas y compiladores puedes hacer lo siguiente:

// define your structure:
#define BUFFSIZE 1024
#define USERLEN 32
#define OPTLEN 16

typedef struct message{
  char option[OPTLEN];
  char user[USERLEN];
  char buff[BUFFSIZE]; 
  char target[USERLEN];
  int sockid;
}my_message;


// now you can use it in your program

my_message m;

// initialize m
...
strcpy(m.user,"1234");
...
m.sockid = sockfd;

// send it over 

if ((nbytes = write(sockfd, &m, sizeof(my_message)) != sizeof(my_message))
{
  printf("error writing my message");
}



// read the message on the other side:
...
my_message received_message;
int size;

if( (size = recv ( sockfd, (void*)&received_message, sizeof(my_message), 0)) >= 0)
{
    //check the size
}

// It would work for same machines 32/64 bits and same compilers.

Si necesita una mejor portabilidad, intente protobuf-c , nanopb , serialización binaria binn o tpl .

0
agregado

Antes de escribir una estructura, debe tener en cuenta los problemas de relleno. Parece que tu estructura está bien alineada. Sin embargo, el receptor debe estar en una arquitectura similar y en una configuración de empaquetado de estructura de compilador similar para consumir la estructura de la misma manera exacta. Alternativamente, puede definir un protocolo de mensaje que empaquete explícitamente estos datos y los escriba como un flujo de bytes.

That said, a structure could still be written simply by doing write(sock, &myMessage, sizeof (message)). It will write out all the bytes of the sizeof(message).

0
agregado

Antes de escribir una estructura, debe tener en cuenta los problemas de relleno. Parece que tu estructura está bien alineada. Sin embargo, el receptor debe estar en una arquitectura similar y en una configuración de empaquetado de estructura de compilador similar para consumir la estructura de la misma manera exacta. Alternativamente, puede definir un protocolo de mensaje que empaquete explícitamente estos datos y los escriba como un flujo de bytes.

That said, a structure could still be written simply by doing write(sock, &myMessage, sizeof (message)). It will write out all the bytes of the sizeof(message).

0
agregado