zTrue
@zTrue

Порядок пакетов (TCP)

Скрипт слушает pcap. Некоторые сообщения, если не помещаются в один пакет, разбиваются на несколько пакетов. Но иногда случается так, что вторая часть сообщения (второй пакет) приходит раньше, чем первая. Мне нужно передавать пакеты приложению в правильном порядке (не обязательно целыми сообщениями, важен только порядок), без существенного таймаута. По идентификаторам пакетов я могу расставить их в нужном порядке, но как я могу быть уверен, что в конкретный момент времени у меня нет «пропущенных» пакетов, которые придут следом? Возможно, какие-то заголовки (о том, что это только часть сообщения)? Если да, то какие?
На данный момент единственное решение, которое вижу — делать таймаут, но оно мне не нравится из-за magic-number таймаута и все-равно отсутствия гарантий.
PS
Модифицировать пакеты или способ их передачи возможности нет.
  • Вопрос задан
  • 7413 просмотров
Решения вопроса 1
@pavelsh
Пока FIN не пришел, вы можете получить еще пакет от той стороны.

А можете пояснить зачем вам node-pcap? Какую задачу хотите сделать?
Ответ написан
Пригласить эксперта
Ответы на вопрос 5
@major
Скрипт слушает tcp сокет == пакеты приходят в правильном порядке (tcp стек все уже сделал самостоятельно)
Ответ написан
@lex_t
TCP гарантирует, что все придет в правильном порядке. Все отправленные пакеты нумеруются
Ответ написан
jcmvbkbc
@jcmvbkbc
"I'm here to consult you" © Dogbert
Если скрипт слушает TCP-сокет стандартными средствами (read/recv), то TCP-стек должен гарантировать доставку данных в правильном порядке. Я думаю, именно это имел в виду major.
По идентификаторам пакетов я могу расставить их в нужном порядке, но как я могу быть уверен, что в конкретный момент времени у меня нет «пропущенных» пакетов, которые придут следом? Возможно, какие-то заголовки (о том, что это только часть сообщения)? Если да, то какие?

Не очень понятно, о каких пакетах и идентификаторах идёт речь. Целостность потока данных TCP обеспечивается полем sequence number заголовка TCP (см. www.ietf.org/rfc/rfc793.txt п 3.1) и длиной принятых данных (вычисляется на основании поля total length из заголовка IP, см. tools.ietf.org/html/rfc791#section-3.1). А именно, каждый переданный байт данных — это +1 к sequence number. Начальный sequence number выбирается случайным образом при установке соединения, т.е. при приёме пакета с флагом SYN. В простейшем случае (без selective ack), каждое установленное соединение должно хранить sequence number ожидаемых данных и сравнивать его с полученным по сети sequence number; в случае их совпадения пропущенных данных нет.
Ответ написан
merlin-vrn
@merlin-vrn
Пакеты, конечно, могут придти в разном порядке. Но вот ядро отдаст данные вашему приложению всегда в правильном порядке.

Т.е. даже если пришли пакеты с SEQ=1, и длиной 1000, а также SEQ = 2501 и длиной 500, то ядро понимая, что чего-то не хватает (пропущено 1500 байтов в середине — второй SEQ, т.е. номер байта, 2501, а мы пока что имели байты вплоть до 1000 включительно), не отдаст на прикладной уровень второй пакет. А по сети ядро будет отправлять ACK 1000, что он получил первый пакет, намекая, что там больше нету.

Как только придёт пакет с SEQ 1001 и какой-нибудь длиной, он будет отдан ядру. Пакет с SEQ=2501, хотя он у ядра давно уже есть, вашему приложению не будет отдан до тех пор, пока все 1500 байтов с номерами 1001 до 2500 включительно не дойдут, по скольким пакетом бы они ни были раскиданы (хоть 1500 пакетов по одному байту). Если в процессе передачи этих промежуточных пакетов произойдёт таймаут, то пакет с SEQ=2501 ваше приложение и не увидит никогда, хотя ядро системы-получателя его имело.

(Хочу обратить внимание на то, что пакеты не пронумерованы. Пронумерованы байты. Поле SEQ в пакете — последовательный номер первого байта данного пакета. Одна тонкость: нумерация начинается не с 0 и не с 1, а со случайного числа, которое определяется отправителем при установке соединения — в пакете с флагом SYN. Пример выше нужно понимать так, что SYN был с SEQ=1).

То есть, о том, что до вас не дойдут промежуточные пакеты, вы можете в случае с TCP не беспокоиться. Если вы на одном конце записали байты в сокет в определённом порядке, вы на другом конце или получите их в точно таком же порядке, или не получите вообще.
Ответ написан
@Sayonji
По-видимому, вы получаете всё-таки сегменты, а не пакеты. В таком случае, если идет сегмент А, а за ним сегмент Б, то разность их идентификаторов (Sequence number) должна быть равна размеру окна (Window size) сегмента А. Если после упорядочивания это не так, значит что-то не пришло.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы