Например, если я отправляю "a" и "b" в совершенно разных пакетах, клиент читает это как "ab". Это случается только один раз, но это создает настоящую проблему в игре.
Я думаю, вы упустили из виду фундаментальную природу TCP: это потоковый протокол, а не пакетный. TCP не учитывает и не сохраняет границы данных отправителя. Иными словами, TCP может объединять (или разделять!) «пакеты», которые вы отправляете, и представлять их получателю так, как он хочет. Единственное ограничение, которое соблюдает TCP, заключается в следующем: если байт доставлен, он будет доставлен в том же порядке, в котором он был отправлен. (И ничто в Нэгле не меняет этого.)
Итак, если вы дважды вызываете send
(или write
) на сервере, отправляя эти шесть байтов:
"packet" 1: A B C
"packet" 2: D E F
Ваша клиентская сторона может recv
(или read
) любую из этих последовательностей байтов:
ABC / DEF
ABCDEF
AB / CD / EF
Если вашему приложению требуется знание границ между write
s отправителя, то вы несете ответственность за сохранение и передачу этой информации.
Как уже говорили другие, есть много способов сделать это. Например, вы можете отправлять новую строку после каждого кванта информации. Так (частично) работают HTTP, FTP и SMTP.
Вы можете отправить длину пакета вместе с данными. Обобщенная форма для этого называется TLV, что означает «Тип, длина, значение». Отправьте поле типа фиксированной длины, поле фиксированной длины, а затем значение произвольной длины. Таким образом, вы узнаете, когда прочитали все значение и готовы к следующему TLV.
Вы можете сделать так, чтобы каждый отправляемый вами пакет был идентичен по длине.
Я полагаю, что есть и другие решения, и я полагаю, что вы можете придумать их самостоятельно. Но сначала вы должны осознать следующее: TCP может и будет объединять или разбивать пакеты вашего приложения. Вы можете полагаться на порядок доставки байтов, но не на что иное.
person
Robᵩ
schedule
07.07.2011