Передача структуры через сокет TCP в C - PullRequest
3 голосов
/ 11 мая 2011

Я пишу небольшое клиент-серверное приложение на C.

На стороне клиента у меня есть одна структура типа

#pragma pack(1)   // this helps to avoid serialization while sending over network. 
typedef struct _viewBoxClient_Info
{
  unsigned long viewBoxID;
  int bRT_flag;
  int nFrameNum;
  char frameData[1000];   
}viewBoxClient_info_send ;
#pragma pack(0)   // turn packing off 

и заполнение переменнойas,

struct _viewBoxClient_Info client_info;
client_info.bRT_flag= 10;/*0 for false, 1 for true*/
client_info.viewBoxID=10000;
memcpy(client_info.frameData,buf,sizeof(client_info.frameData)); //char buf[] data is "is 1st line"
client_info.nFrameNum=1;

и отправка на сервер с помощью следующей функции,

send(sock, (char *)&client_info, bytesRead, 0);

На стороне сервера у меня есть одна структура, подобная (такая же, как структура на стороне клиента),

#pragma pack(1)   // this helps to avoid serialization while sending over network.
typedef struct _lclviewBoxClient_Info
{
 unsigned long viewBoxID;
 int bRT_flag;
 int nFrameNum;
 char frameData[1000];
}viewBoxClient_info_receive ;
#pragma pack(0)   // turn packing off

и получение сообщения и печать на экране как,

viewBoxClient_info_receive lcl_viewBox;
ssize_t bytesReceived = recv( *nfd, &lcl_viewBox, sizeof(struct _lclviewBoxClient_Info), 0);
printf("\nlcl_viewBox.bRT_flag:%d\n",lcl_viewBox.bRT_flag);
printf("lcl_viewBox.nFrameNum:%d\n",lcl_viewBox.nFrameNum);
printf("lcl_viewBox.frameData:%s\n",lcl_viewBox.frameData);

O / p на экране сервера,

 lcl_viewBox.bRT_flag:1
 lcl_viewBox.nFrameNum:1936287860
 lcl_viewBox.frameData: is 1st line

Я делаюне знаю, что именно происходит на моей стороне сервера.Я отправляю 10 для bRT_flag от клиента и получаю 1 на сервере.Также отправка nFrameNum = 1 от клиента и получение как nFrameNum: 1936287860 на сервере.frameData также на стороне клиента я отправляю "Это 1-я строка", а при получении сервером только "1-я строка".Поможет ли кто-нибудь, чтобы избавиться от этой проблемы?

спасибо и всего наилучшего,

Шри

Ответы [ 3 ]

2 голосов
/ 11 мая 2011

Отправлять необработанные структуры, как это, очень плохая идея.

Вам приходится иметь дело с порядком байтов (порядком байтов), упаковкой (которая все еще может быть проблемой даже при #pragma pack) и другой проблемой, с которой вы сталкиваетесь, это то, что размеры типов, таких как 'int', могут варьироваться в зависимости от платформы.

Я бы порекомендовал библиотеку сериализации, такую ​​как Буферы протокола Google , чтобы помочь вам в этом. Если вы все еще хотите сделать это самостоятельно, вам нужно поискать такие функции, как htonl для преобразования целочисленных типов в сетевой порядок байтов, и начать использовать примитивы фиксированного размера, такие как uint32_t и т. Д.

Вам также следует прекратить отправку всей структуры сразу и вместо этого написать вспомогательные функции, такие как writeClientStruct (int sock, struct client_struct *), которые будут отправлять каждое значение элемента отдельно, чтобы избежать проблем упаковки между платформами.

2 голосов
/ 11 мая 2011

Не должно ли это:

send(sock, (char *)&client_info, bytesRead, 0);

быть:

send(sock, (char *)&client_info, sizeof( client_info ), 0);

И вы должны проверить возвращаемое значение send () и особенно recv () - нет гарантии, что вызов recv получит вашу структуру за один раз.

0 голосов
/ 11 мая 2011

Одним из объяснений может быть то, что ваш клиент и сервер по-разному интерпретируют размер "unsigned long".(Работает на разных машинах или разных опциях компилятора, другие 32-битные и 64-битные).

Это объясняет симптомы:

  • bRT_flag смещен на 32 бита дляnFrameNum
  • nFrameNum, содержащий первые 32 бита из frameData (1936287860 -> 0x73696874 -> "siht" -> с подстановкой на порядковый номер "this")

Тривиальная проверка для этого будетпроверьте sizeof (struct) или sizeof (unsigned long), чтобы увидеть, совпадают ли они.

Пожалуйста, ознакомьтесь с публикацией Майка Веллера о том, как это исправить.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...