как правильно использовать вызов recv () sys - PullRequest
0 голосов
/ 31 января 2012

Я нахожусь в процессе написания TCP-сервера с использованием Berkely SOCKET API под Linux.Теперь клиенты имеют набор спецификаций, и каждое сообщение, отправляемое клиентом, основано на этих спецификациях, т.е. сообщение, отправленное клиентом, соответствует одной из многих структур, указанных в спецификациях.Теперь сценарий таков, что сервер не знает, какое сообщение клиент будет отправлять в какое время.Как только мы получим сообщение, мы можем выяснить, что это такое, но не раньше.Сообщения, отправляемые клиентами, имеют переменную длину, поэтому мы не можем заранее знать, какое сообщение мы собираемся получить.Чтобы решить эту проблему, я использовал следующий метод:

const char *buf[4096] = { 0 };
          if ( recv (connected, buf, 4096, 0) == -1)
             {
               printf ("Error in recvng message\n");
               exit (-1);
             }

То есть я использую буфер по умолчанию размером 4096 (ни одно сообщение от клиента не может быть больше этого размера).получить в этом буфере, а затем я проверяю тип сообщения и предпринимаю соответствующее действие следующим образом:

struct ofp_header *oph;
oph=(struct ofp_header *)buf;
switch (oph->type)
{
case example_pkt:
handle_example_pkt();
break;
}

Это работает нормально, но я просто хотел подтвердить, что это подходящий метод или есть что-то еще, чтоможет быть лучше, чем это.Вся помощь очень ценится.

Спасибо.

1 Ответ

5 голосов
/ 31 января 2012

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

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

  1. Измените протокол так, чтобы размер каждого сообщения отправлялся в качестве первых нескольких байтов сообщения.Сначала прочитайте размер, затем прочитайте только столько байтов.

  2. Поскольку вы знаете размер каждого сообщения, следите за тем, сколько байтов вы прочитали.Обработайте первое сообщение в буфере, затем вычтите размер этого сообщения из оставшихся байтов в буфере.Продолжайте повторять этот процесс до тех пор, пока вы не будете либо A. Не иметь достаточно байтов для идентификации типа сообщения, либо B. Не иметь достаточно байтов для сообщения обнаруженного типа.Сохраните оставшиеся байты и снова вызовите recv, чтобы прочитать больше данных.

...