В наших приложениях, использующих протокол TCP, часто возникает проблема «прилипания» пакетов. Проще говоря, так называемый липкий пакет означает, что у меня есть два сообщения. Код на отправляющей стороне, очевидно, отправляется два раза, но принимающая сторона получает сразу два сообщения. Такая ситуация очень распространена как в индустрии встраиваемых систем, так и в индустрии Интернета.
Тогда вам нужно сначала понять определение TCP. TCP (протокол управления передачей) — это ориентированный на соединение надежный протокол связи транспортного уровня на основе байтовых потоков.
Среди них один, наиболее связанный с липкими пакетами, основан на функции потока байтов. Поток байтов можно понимать как данные, передаваемые по двунаправленному каналу. Эти данные на самом деле представляют собой то, что мы часто называем двоичными данными. Проще говоря, это множество строк 01. Между этими строками 01 нет границ.
Данные, передаваемые с прикладного уровня по протоколу TCP, не передаются хосту назначения в блоках сообщений, а передаются в нисходящий поток в виде потоков байтов. Эти данные могут быть разрезаны и собраны в различные пакеты данных и получены. конец получает эти сообщения. Предыдущие сообщения не были правильно восстановлены после пакета данных, поэтому произошло зависание пакета.
1. Причины на отправляющей стороне
Когда отправитель собирает сообщение, он объединяет несколько небольших пакетов в один пакет, поэтому принимающая сторона, естественно, не может анализировать небольшие пакеты. Это соответствует алгоритму Нэгла. Поскольку TCP и алгоритм Нэгла являются продуктами прошлого века, использование этого в ранних сетях может значительно снизить нагрузку на сеть. В противном случае частая отправка небольших пакетов длиной всего в несколько байт приведет к серьезному снижению производительности ввода-вывода в сети.
Однако в современном Интернете производительность сети значительно улучшилась. Похоже, что производительность ввода-вывода, улучшенная алгоритмом Нэгла, не так важна. Напротив, из-за ожидания объединения данных задержка передачи станет больше. . При использовании онлайн-игр это сильно повлияет на впечатления. Так теперь он вообще отключен.
2. Причины на принимающей стороне
После того, как принимающая сторона получит сообщение, уровень приложения не всегда может немедленно забрать данные, и всегда будет буфер приема. Если интервал между двумя независимыми сообщениями, поступающими в буфер, слишком мал и прикладной уровень не может получить последнее сообщение между двумя сообщениями, то при следующем его чтении два пакета сообщений неизбежно будут считаны одновременно. что также вызывает липкие мешки.
И этой ситуации нельзя избежать, позволяя отправителю отправлять пакеты равномерно по времени, поскольку из-за существования нестабильности сети даже пакеты данных, отправленные равномерно по времени, могут случайно появляться на принимающей стороне.
Как избежать негативного воздействия липких пакетов?
На основе приведенного выше анализа нетрудно обнаружить, что предотвратить проблему липких пакетов в принципе невозможно. Даже если отправитель и получатель могут контролировать себя, процесс сетевой передачи контролировать сложно.
Но даже если проблема липких пакетов существует, она не повлияет на наше широкомасштабное использование протокола TCP. Потому что с этой проблемой очень легко справиться на уровне приложения. Есть примерно две идеи:
1. Добавьте специальные флаги в качестве разделителей в сообщении.
Таким образом, когда уровень приложения обнаружит специальный разделитель, он будет знать, что это начало и конец пакета, и сможет выполнять такие операции, как фрагментация, и проблема будет решена.
Однако в этом есть некоторые недостатки. Например, если разделитель определен как «12345678», что, если в содержимом сообщения появится строка «12345678»? Это приведет к ненормальной нарезке сообщения, что приведет к ошибке в полученном сообщении. Но если вы можете контролировать содержимое сообщения и следить за тем, чтобы в нем не появлялось «12345678», этот метод является более гибким.
2. Добавьте длину сообщения
Считайте информацию о длине сообщения на основе согласованного поля длины, а затем прочитайте содержимое сообщения на основе информации о длине сообщения. Это также очень распространенный метод, отраженный во многих протоколах.
3. Добавьте заголовок пакета.
Отправляющая сторона добавляет заголовок пакета к каждому пакету данных. Заголовок должен содержать как минимум длину пакета данных. Таким образом, после получения данных принимающая сторона может узнать фактическую длину каждого пакета данных, прочитав длину. поле заголовка пакета.