Признаются ли срочные данные TCP?
В сегменте tcp с флагом URG могут быть и обычные данные. Как принимающий хост обрабатывает срочный пакет? Как он подтверждает срочные данные, если они не являются частью потока данных? Это признает остальное?
Я понимаю, что он обычно не используется, но если оба хоста поддерживают один и тот же RFC относительно флага URG, как они обрабатывают внеполосные данные?
Если срочными данными является сообщение об отмене, получатель отбросит все остальные данные, но отправителю все равно потребуется подтверждение о получении сообщения.
1 ответ
Немного предыстории:
Срочный механизм TCP позволяет определить точку в потоке данных как конец срочной информации. Таким образом, у нас есть Urgent Pointer, который содержит положительное смещение от порядкового номера в этом сегменте tcp. Это поле имеет значение только с установленным битом управления URG.
Расхождения по срочному указателю:
RFC 793 (1981, стр. 17):
Срочный указатель указывает на порядковый номер октета, следующего за срочными данными.
RFC 1011 (1987, стр. 8):
Страница 17 не так. Указатель срочности указывает на последний октет срочных данных (не на первый октет несрочных данных).
То же самое в RFC 1122 (1989, стр. 84):
... указатель срочности указывает на порядковый номер октета LAST (не LAST+1) в последовательности срочных данных.
В понятном RFC 6093 (2011, стр. 6-7) говорится:
Принимая во внимание, что до тех пор, пока отправитель TCP и получатель TCP реализуют одинаковую семантику для указателя Urgent, нет никакой функциональной разницы в том, чтобы указатель Urgent указывал на "порядковый номер октета после срочных данных" против "последнего" октет срочных данных ", и что все известные реализации интерпретируют семантику срочного указателя как указывающую на" порядковый номер октета, следующего за срочными данными ".
Таким образом, обновление RFC 793, RFC 1011 и RFC 1122
указатель срочности указывает на порядковый номер октета, следующего за срочными данными.
Он соответствует практически всем существующим реализациям TCP.
Примечание: Linux предоставляет net.ipv4.tcp_stdurg
sysctl
переопределить поведение по умолчанию, но это sysctl
влияет только на обработку входящих сегментов. Срочный указатель в исходящих сегментах будет по-прежнему установлен в соответствии с RFC 793.
Об обработке данных
Вы можете получить срочные данные двумя способами (имейте в виду, что концепция TCP "срочные данные" отображается в API сокета как "данные вне диапазона"):
- с помощью
recv
сMSG_OOB
флаг установлен. (обычно вы должны установить право собственности на сокет с чем-то вродеfcntl(sock, F_SETOWN, getpid());
и установить обработчик сигнала дляSIGURG
). Таким образом, вы будете уведомлены сSIGURG
сигнал. Данные будут прочитаны отдельно от обычного потока данных. с помощью
recv
безMSG_OOB
флаг установлен. Ранее вы должны установитьSO_OOBINLINE
Опция сокета такая:int so_oobinline = 1; /* true */
setsockopt(sock, SOL_SOCKET, SO_OOBINLINE, &so_oobinline, sizeof so_oobinline);
Данные остаются "встроенными". И вы можете определить срочно указатель с помощью
ioctl
:int flag; /* True when at mark */
ioctl(sock, SIOCATMARK, &flag);
Кроме того, для новых приложений рекомендуется вообще не использовать механизм срочных данных, чтобы использовать (если это так) прием в режиме реального времени, как упоминалось выше.
Из RFC 1122:
Срочный механизм TCP НЕ является механизмом отправки "внеполосных" данных: так называемые "срочные данные" должны доставляться "в линию" пользователю TCP.
Также из RFC 793:
TCP не пытается определить, что конкретно делает пользователь, получив уведомление об ожидающих срочных данных
Таким образом, вы можете справиться, как вы хотите. Это проблема уровня приложения.
Соответственно, ответ на ваш вопрос о подтверждениях, когда все другие данные были отброшены, звучит так: "Вы можете реализовать их в своем приложении".
Что касается tcp-ack, я не нашел ничего особенного в случае срочных данных.
О длине "Срочных данных"
Практически все реализации действительно могут предоставить только один байт "внеполосных данных".
RFC 6093 говорит:
Если последовательные указания "срочных данных" получены до того, как приложение считывает ожидающий "внеполосный" байт, этот ожидающий байт будет отброшен (то есть перезаписан новым байтом "срочных данных").
Таким образом, режим срочности TCP и его указатель срочности не могут обеспечить маркировку границ срочных данных на практике.
Ходят слухи, что есть некоторые реализации, которые ставят в очередь каждый из полученных срочных байтов. Известно, что некоторые из них не обеспечивают каких-либо ограничений на количество "срочных данных", которые они ставят в очередь. Таким образом, они становятся уязвимыми для тривиальных атак исчерпания ресурсов.
PS Все вышеперечисленное, вероятно, охватывает чуть больше, чем просили, но это только для того, чтобы дать понять людям, незнакомым с этой проблемой.
Еще несколько полезных ссылок:
TCP Urgent Pointer, управление буфером и вызов "Отправить"
Разница между push и срочными флагами в TCP
Понимание срочного указателя