один вызов recv () может получить данные от 2 последовательных вызовов send ()? - PullRequest
3 голосов
/ 22 мая 2011

У меня есть клиент, который отправляет данные на сервер с двумя последовательными вызовами отправки:

send(_sockfd,msg,150,0);
send(_sockfd,msg,150,0);

, и сервер получает, когда был отправлен первый вызов отправки (скажем, я использую select):

recv(_sockfd,buf,700,0);

обратите внимание, что буфер, который я получаю, намного больше.

Мой вопрос: есть ли вероятность, что buf будет содержать обе msgs?мне нужно 2 вызова recv (), чтобы получить оба сообщения?

спасибо!

Ответы [ 3 ]

4 голосов
/ 22 мая 2011

TCP - это протокол , ориентированный на поток .Не ориентированный на сообщение / запись / чанк.То есть, все, что гарантировано, это то, что если вы отправляете поток, байты попадут на другую сторону в том порядке, в котором вы их отправили.В RFC 793 или любом другом документе нет положений о количестве задействованных сегментов / пакетов.

Это резко контрастирует с UDP.Как правильно сказал @R .., в UDP все сообщение отправляется за одну операцию (обратите внимание на изменение терминологии: message).Попробуйте отправить гигантское сообщение (в несколько раз больше, чем MTU) по TCP?Это нормально, он разделит его для вас.

При работе в локальных сетях или на локальном хосте вы наверняка заметите, что (как правило) one send == one recv.Не думай об этом.Есть факторы, которые сильно меняют его.Среди этих

  • Nagle
  • Базовый MTU
  • Использование памяти (возможно)
  • Таймеры
  • Многие другие

Конечно, отсутствие соответствия между send и recv является неудобством, и вы не можете полагаться на UDP.Это одна из причин SCTP.SCTP - действительно очень интересный протокол, и он ориентирован на сообщения .

Возвращаясь к TCP, это обычная неприятность.Не менее распространенным решением является следующее:

  • Установить, что все пакеты начинаются с последовательности фиксированной длины (скажем, 32 байта)
  • Эти 32 байта содержат (возможно,среди прочего) размер сообщения , следующего за
  • Когда вы читаете любой объем данных из сокета, добавьте данные в буфер, определенный для этого соединения.Когда достигнут 32 байт , прочитайте длину, которую вам все еще нужно прочитать, пока не получите сообщение.

Очень важно заметить, что на самом деле нет сообщений в сети.только байты.Как только вы это поймете, вы совершите гигантский шаг к написанию сетевых приложений.

1 голос
/ 22 мая 2011

Ответ зависит от типа сокета, но в целом да, это возможно. Для TCP это норма. Для UDP я считаю, что это не может произойти, но я не эксперт по сетевым протоколам / программированию.

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

Да, может и часто делает. При использовании TCP / IP невозможно сопоставить отправку и получение вызовов. Логика вашей программы должна проверять возвращаемые значения вызовов send и recv в цикле, который завершается, когда все отправлено или получено.

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