TCP
- это протокол , ориентированный на поток .Не ориентированный на сообщение / запись / чанк.То есть, все, что гарантировано, это то, что если вы отправляете поток, байты попадут на другую сторону в том порядке, в котором вы их отправили.В RFC 793 или любом другом документе нет положений о количестве задействованных сегментов / пакетов.
Это резко контрастирует с UDP
.Как правильно сказал @R .., в UDP
все сообщение отправляется за одну операцию (обратите внимание на изменение терминологии: message
).Попробуйте отправить гигантское сообщение (в несколько раз больше, чем MTU) по TCP?Это нормально, он разделит его для вас.
При работе в локальных сетях или на локальном хосте вы наверняка заметите, что (как правило) one send == one recv
.Не думай об этом.Есть факторы, которые сильно меняют его.Среди этих
- Nagle
- Базовый MTU
- Использование памяти (возможно)
- Таймеры
- Многие другие
Конечно, отсутствие соответствия между send
и recv
является неудобством, и вы не можете полагаться на UDP
.Это одна из причин SCTP
.SCTP
- действительно очень интересный протокол, и он ориентирован на сообщения .
Возвращаясь к TCP
, это обычная неприятность.Не менее распространенным решением является следующее:
- Установить, что все пакеты начинаются с последовательности фиксированной длины (скажем, 32 байта)
- Эти 32 байта содержат (возможно,среди прочего) размер сообщения , следующего за
- Когда вы читаете любой объем данных из сокета, добавьте данные в буфер, определенный для этого соединения.Когда достигнут 32 байт , прочитайте длину, которую вам все еще нужно прочитать, пока не получите сообщение.
Очень важно заметить, что на самом деле нет сообщений в сети.только байты.Как только вы это поймете, вы совершите гигантский шаг к написанию сетевых приложений.