Olej писал(а):
mcrandy писал(а):
У меня есть своя клиент-серверная программка организующая передачу рандомного сообщения заданной длины. В ней используются стандартные функции send() и recv() для передачи/приема соответственно. Используется протокол TCP. Она осложнена только тем что в начало сообщения записывает длину этого сообщения которое собирается передать, чтобы сервер знал сообщение какой длины ему ожидать. Программку прикрепляю к сообщению. Внутри есть небольшой README.
Сомнения вызывают выделенные мной в цитате слова:
В TCP
нет "сообщений" (а ещё более вводит в заблуждение когда говорят "пакет") - это есть в UDP.
Сокет TCP - это поток, stream ... это "труба", в которую в один конец вливается, а из другого выливается
Очень часто неявно предполагают, что если, например, клиент передаёт последовательность сообщений фиксированной длины:
... 10, 10, 10, 10, ... и т.д.
то и на приёмной стороне (сервер) будет такая же последовательность длин принимаемых recv():
Код: Выделить всё
while(...) {
len = recv( sock, ptr, nrd, MSG_NOSIGNAL );
...
}
А это
принципиально не так!
На приёмном конце могут появляться len ("пакеты") хоть такой длины:
... 10, 5, 5, 10, ...
хоть такой:
... 10, 20, 20, 10 ...
хоть даже такой
... 10, 13, 17, 10, ...
А это значит, что сами "сообщения" в потоке TCP можете
разграничивать только вы сами.
И сделать это можно только 2-мя способами (я только эти знаю), точно так же как с текстовыми строками (char* и string ... то, как это делается в языках C и PASCAL):
1. завершая сообщение фиксированным разделителем ('\0', например, или -1, или ...);
2. указывая в сообщении (в голове) длину последующего тела сообщения.
Так что наличие длины в голове сообщения не "осложняет" приём сообщений по TCP, а единственно только и делает их возможным!
Но в любом случае обратите внимание на то, что:
- после того как вы выгребете текущее сообщение из буфера приёма...
- там в хвосте, за выбранным сообщением, может быть ещё одно полное сообщение...
- или может быть только несколько начальных байт следующего сообщения...
- и если вы их отбросите, то вы
потеряете синхронизацию с сообщениями (с их разметкой) и уже
не сможете больше принимать последующие сообщения ... считайте, что ваш сервер "завис".
Эти эффекты возникают из-за весьма сложной алгоритмики TCP, таких механизмов как:
- алгоритм Нэйгла;
- отсроченные подтверждения;
- "медленный старт";
- адаптивное изменение размеров окон передачи и прийма;
... там довольно много таких механизмов, связано это с оптимизацией.
Огромной неприятностью (говорю это по опыту завершённых и внедрённых проектов) таких эффектов есть то, что:
- они практически почти не проявляются в LAN (там оптимизировать особенно нечего), поэтому их
не видно при отладке ... "похоже что всё работает нормально" - но это до поры до времени...
- а в реальной установленной системе они проявляются тоже с малыми вероятностями ... я реально ловил 10**-9 (1 прокол на несколько сот миллионов посылок)...
- и выглядит тогда это так: система работает ... сутки, двое ... а потом "неожиданно" валится.
Поэтому такие вещи нужно
не отлаживать, а сразу писать код понимая что и как будет происходить.