Это правдоподобно в C / C ++ сокетах? - PullRequest
3 голосов
/ 05 июня 2011

У меня сейчас базовая настройка клиент / сервер. Сервер должен принимать запросы от клиента (ов) и должен отвечать на сообщения разных типов. Примером запроса клиента может быть получение списка доступных файлов, сколько других клиентов подключено к серверу и т. Д.

Я бы, очевидно, должен был найти способ определить тип сообщения из сообщения, полученного от отправителя. Мне было интересно, если у меня есть структура, определенная с необходимыми данными, могу ли я привести структуру к void *, отправить ее как через системный вызов send (sockfd, message, length, flags), а затем на стороне получателя - вернуться к структуре. Это, конечно, предполагает, что я запускаю клиент и сервер в одной среде.

Например, если у меня есть следующая структура:

struct message {
   enum messageType { GET_FILES, GET_CLINET_NUMBER} messageType,
} 

и используйте эту структуру для отправки сообщения следующим образом

struct message msg;
msg.messageType = GET_FILES;
send(server_sockfd, (void*)&msg, sizeof(struct), 0)

и на приемнике

recv(,msg_buffer);
struct message received = (struct message*)msg_buffer;

Игнорируя незначительные синтаксические проблемы, кто-нибудь может посоветовать, возможна ли эта схема? Если нет, есть ли другой способ передать сообщение, не отправляя raw char *?

Ответы [ 3 ]

4 голосов
/ 05 июня 2011

Это вполне возможно.Однако не рекомендуется, потому что теперь вы используете одну и ту же среду для клиента и сервера, но вы можете измениться в будущем, и вам придется изменить этот код, чтобы он был более независимым от платформы / реализации.

Варианты?boost :: serialization, XML-RPC, даже HTTP / REST или любой другой протокол высокого уровня, который вам подходит, буфер протокола Google, CORBA и т. д.

1 голос
/ 05 июня 2011

Необходимо помнить о двух вещах:

  1. Порядковый номер .Если порядковые номера вашего клиента и сервера расходятся, вы окажетесь в ситуации, когда вы не можете общаться.Учитывая, что сегодня большое внимание уделяется системам x86, вы можете убедить себя чувствовать себя комфортно с этим ограничением.Если бы я был тобой, я бы, как минимум, встроил валидацию.Например, в начале каждого сеанса связи отправляйте известную контрольную сумму, например, 0xdeadbeef.Это позволило бы вам утверждать, что порядковый номер между клиентом и сервером одинаков, надеясь избежать продолжения сеанса и всех возможных ошибок.

  2. Размер слова .Это более коварная и сильная причина, почему вы не должны делать то, о чем вы думаете.Если вы не можете строго утверждать, что размер слова отправителя и получателя никогда не будет отличаться, то ваш метод чреват опасностью.Предположим, у вас есть следующая структура:

    struct some_msg { long payload; };

    Что происходит, когда 32-разрядная система gcc / linux отправляет это сообщение в 64-разрядную систему gcc / linux?Что ж, в 32-битной системе она с удовольствием отправит 4 байта данных.Тем не менее, 64-битная система наложит структуру на 8 байтов данных.Плохие новости несут в себе.

Хотя вы вряд ли перейдете с x86 на sparc, но почти наверняка ваши системы будут 64-битными.Мне неизвестно, есть ли у вас устаревшие 32-битные системы, но без очень жесткого контроля над клиентом и сервером практически гарантируется, что у вас будет среда со смешанным размером слов.

Я уверен, что это может бытьсделано для работы, если вы очень определенно определяете и управляете используемыми платформами.Кроме того, вы можете ограничить свой риск, используя фиксированные типовые значения, такие как int32_t и uint64_t.Вы играете с огнем, ИМО, если вы делаете это.Любое возможное преимущество быстро уменьшается благодаря высокой степени привязанности вашего проектирования к вашей системе.

0 голосов
/ 05 июня 2011

'может привести структуру к void *, отправить ее как через системный вызов send (sockfd, message, length, flags), а затем на стороне получателя привести ее обратно к структуре' - см. Ответ Диего.Обратите внимание, что любой протокол, который не может восстановиться или, что еще хуже, фактически приведет к сбою сервера, если один дополнительный случайный байт вставлен / удален / изменен в потоке, недостаточно защищен, транспортируется по TCP или нет.

'Если нет, есть ли другой способ передать сообщение без отправки raw char *? 'Единственная альтернатива протоколу, который может надежно и корректно пересобрать сообщения из байта (октета), strean, - это отключать / повторно соединять после каждого сообщения, таким образом прерывая поток.Производительность / задержка этой схемы - именно то, что вы ожидаете - очень, очень плохо.

Rgds, Martin

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