Выше мы использовали термины «срочный указатель» (urgent pointer) и «срочное смещение» (urgent offset). На уровне TCP эти термины имеют различные значения. Величина, представленная 16 битами в заголовке TCP, называется срочным смещением и должна быть прибавлена к полю последовательного номера в заголовке TCP для получения 32-разрядного последовательного номера последнего байта срочных данных (то есть срочного указателя). TCP использует срочное смещение, только если в заголовке установлен другой бит, называемый флагом URG. Программисту можно не заботиться об этом различии и работать только со срочным указателем TCP.
Важная характеристика срочного режима TCP заключается в следующем: заголовок TCP указывает на то, что отправитель вошел в срочный режим (то есть флаг URG установлен вместе со срочным смещением), но фактической отправки байта данных, на который указывает срочный указатель, не требуется. Действительно, если поток данных TCP остановлен функциями управления потоком (когда буфер приема сокета получателя заполнен и TCP получателя объявил нулевое окно для отправляющего TCP), то срочное уведомление отправляется без каких-либо данных [128, с. 1016–1017], как показано в листингах 24.8 и 24.9. Это одна из причин, по которой в приложениях используется срочный режим TCP (то есть внеполосные данные): срочное уведомление всегда отсылается собеседнику, даже если поток данных остановлен функциями управления потоком TCP.
Что произойдет, если мы отправим несколько байтов внеполосных данных, как в следующем примере?
send(fd, "abc", 3, MSG_OOB);
В этом примере срочный указатель TCP указывает на байт, следующий за последним байтом, и таким образом, последний байт (с
) считается байтом внеполосных данных.
Посмотрим теперь, как выглядит процесс отправки внеполосных данных с точки зрения принимающей стороны.
1. Когда TCP получает сегмент, в котором установлен флаг URG, срочный указатель проверяется для выяснения того, указывает ли он на
2. Принимающий процесс извещается о том, что прибыли новые внеполосные данные. Сначала владельцу сокета посылается сигнал SIGURG
. При этом предполагается, что для установления владельца сокета была вызвана функция fcntl
или ioctl
(см. табл. 7.9) и что для данного сигнала процессом был установлен обработчик сигнала. Затем, если процесс блокирован в вызове функции select
, которая ждет возникновения исключительной ситуации для дескриптора сокета, происходит возврат из этой функции.
Эти два уведомления действуют в том случае, когда прибывает новый срочный указатель, вне зависимости от того, принят ли байт, на который он указывает.
В потоке данных может быть только одна отметка OOB (один срочный указатель). Если новый срочный байт отправляется до того, как будет принят старый, последний просто сбрасывается и перестает быть срочным.
3. Когда байт данных, на который указывает срочный указатель, фактически прибывает на принимающий TCP, этот байт может быть помещен отдельно или оставлен вместе с другими данными. По умолчанию параметр сокета SO_OOBINLINE
recv
, recvfrom
или recvmsg
с заданием флага MSG_OOB
. Если новый срочный байт прибывает до того, как будет считан старый, новое значение записывается в буфер поверх прежнего.
Однако если процесс устанавливает параметр сокета SO_OOBINLINE
, то байт данных, на который указывает срочный указатель TCP, остается в обычном буфере приема сокета. В этом случае процесс не может задать флаг MSG_OOB
для считывания данных, содержащихся во внеполосном байте. Процесс сможет распознать этот байт, только когда дойдет до него и проверит
1. Если процесс запрашивает внеполосные данные (то есть устанавливает флаг MSG_OOB
), но собеседник таких данных не послал, возвращается EINVAL
.