Protocol-Independent внеполосные данные
Абстракция сокета потока включает понятие внеполосных данных (OOB). Многие протоколы позволяют тем или иным образом помечать части входящих данных как специальные, и эти специальные блоки данных могут быть доставлены пользователю вне обычной последовательности. Примеры включают ускоренную передачу данных в X.25 и других протоколах OSI, а также срочные данные в использовании TCP в BSD UNIX. В следующем разделе описывается обработка данных OOB независимым от протокола способом. Обсуждение данных OOB, реализованных с помощью срочных данных TCP, следует за независимым от протокола объяснением. В каждом обсуждении использование recv также подразумевает recvfrom, WSARecv и WSARecvFrom, а ссылки на WSAsyncSelect также применяются к WSAEventSelect.
Данные OOB, независимые от протокола
Данные OOB — это логически независимый канал передачи, связанный с каждой парой подключенных сокетов потока. Данные OOB могут быть доставлены пользователю независимо от обычных данных. Абстракция определяет, что объекты данных OOB должны поддерживать надежную доставку по крайней мере одного блока данных OOB за раз. Этот блок данных может содержать по крайней мере один байт данных, и по крайней мере один блок данных OOB может находиться в состоянии ожидания доставки пользователю в любой момент времени. Для протоколов связи, поддерживающих передачу сигналов в канале (например, TCP, где срочные данные доставляются в последовательности с обычными данными), система обычно извлекает данные OOB из обычного потока данных и сохраняет их отдельно (оставляя пробел в обычном потоке данных). Это позволяет пользователям выбирать между получением данных OOB в порядке и их получением из последовательности без необходимости буферизации всех промежуточных данных. Вы можете заглянуть на внеполосные данные (OOB).
Пользователь может определить, ожидают ли какие-либо данные OOB для чтения, с помощью функции ioctlsocket или WSAIoctl с SIOCATMARK IOCTL. Для протоколов, в которых концепция положения блока данных OOB в обычном потоке данных имеет смысл, например TCP, поставщик службы Сокетов Windows сохраняет концептуальный маркер, указывающий положение последнего байта данных OOB в нормальном потоке данных. Это необязательно для реализации функций ioctlsocket или WSAIoctl , поддерживающих SIOCATMARK. Наличие или отсутствие данных OOB является обязательным.
Для протоколов, в которых концепция положения блока данных OOB в обычном потоке данных имеет смысл, приложение может обрабатывать внеполосные данные как часть обычного потока данных. Это достигается путем установки параметра сокета SO_OOBINLINE с помощью функции setsockopt . Для других протоколов, где блоки данных OOB действительно не зависят от обычного потока данных, попытка задать SO_OOBINLINE приводит к ошибке. Приложение может использовать функцию ioctlsocket или WSAIoctl с IOCTL SIOCATMARK , чтобы определить, есть ли непрочитанные данные OOB перед меткой. Например, он может использовать эти сведения для повторной синхронизации со своим одноранговым элементом, гарантируя, что все данные, вплоть до метки в потоке данных, будут удалены при необходимости.
Если SO_OOBINLINE отключен (параметр по умолчанию):
- Сокеты Windows уведомляют приложение о событии FD_OOB, если приложение зарегистрировано для уведомления с помощью WSAsyncSelect, точно так же, как FD_READ используется для уведомления о наличии обычных данных. То есть FD_OOB публикуется, когда данные OOB поступают без данных OOB, ранее поставленных в очередь. FD_OOB также публикуется при чтении данных с помощью флага MSG_OOB, в то время как некоторые данные OOB остаются в очереди после возврата операции чтения. FD_READ сообщения не публикуются для данных OOB.
- Сокеты Windows возвращаются при выборе с соответствующим набором сокета exceptfds, если данные OOB помещены в очередь в сокет.
- Приложение может вызывать recv с MSG_OOB для чтения срочного блока данных в любое время. Блок данных OOB переходит в очередь.
- Приложение может вызывать recv без MSG_OOB для чтения обычного потока данных. Блок данных OOB не отображается в потоке данных с обычными данными. Если данные OOB остаются после любого вызова recv, сокеты Windows уведомляют приложение FD_OOB или с исключениемfds при использовании select.
- Для протоколов, где данные OOB имеют позицию в обычном потоке данных, одна операция recv не охватывает эту позицию. Один recv возвращает обычные данные перед меткой, а второй recv требуется, чтобы начать чтение данных после метки.
С включенным SO_OOBINLINE:
- FD_OOB сообщения не публикуются для данных OOB. Данные OOB обрабатываются как обычные для функций select и WSAAsyncSelect и указываются путем установки сокета в readfds или отправки сообщения FD_READ соответственно.
- Приложение не может вызвать recv с флагом MSG_OOB, установленным для чтения блока данных OOB. Возвращается код ошибки WSAEINVAL.
- Приложение может вызывать recv без установленного флага MSG_OOB. Все данные OOB доставляются в правильном порядке в обычном потоке данных. Данные OOB никогда не смешиваются с обычными данными. Для получения данных OOB требуется три запроса на чтение. Первый возвращает обычные данные до блока данных OOB, второй возвращает данные OOB, третий возвращает обычные данные после данных OOB. Другими словами, границы блока данных OOB сохраняются.
Подпрограмма WSAsyncSelect особенно хорошо подходит для обработки уведомлений о наличии внеполосных данных, когда SO_OOBINLINE отключена.
Данные OOB в TCP
Важно!
Следующее обсуждение внеполосных данных (OOB), реализованных с помощью срочных данных TCP, соответствует модели, используемой в распространении программного обеспечения в Беркли. Пользователи и разработчики должны помнить, что:
В настоящее время существует две противоречивые интерпретации RFC 793 (где вводится эта концепция).
Реализация данных OOB в дистрибутиве программного обеспечения Беркли (BSD) не соответствует требованиям узла, указанным в RFC 1122.
В частности, указатель tcp urgent в BSD указывает на байт после байта срочных данных, а соответствующий RFC указатель TCP urgent указывает на байт срочных данных. В результате, если приложение отправляет срочные данные из реализации, совместимой с BSD, в реализацию, совместимую с RFC 1122, получатель считывает неправильный байт срочных данных (он считывает байт, расположенный после правильного байта в потоке данных, как срочный байт данных).
Чтобы свести к минимуму проблемы взаимодействия, записи приложений рекомендуется не использовать данные OOB, если это не требуется для взаимодействия с существующей службой. Поставщикам сокетов Windows настоятельно рекомендуется задокументировать семантику OOB (BSD или RFC 1122), которую реализует их продукт.
Получение сегмента TCP с флагом URG (for urgent) указывает на наличие одного байта данных OOB в потоке данных TCP. Блок данных OOB имеет размер в один байт. Указатель urgent — это положительное смещение от текущего порядкового номера в заголовке TCP, указывающее расположение блока данных OOB (неоднозначно, как указано выше). Таким образом, он может указывать на еще не полученные данные.
Если SO_OOBINLINE отключен (по умолчанию) при поступлении сегмента TCP, содержащего байт, на который указывает срочный указатель, блок данных OOB (один байт) удаляется из потока данных и помещается в буфер. Если последующий сегмент TCP поступает с установленным флагом срочной проверки (и новым указателем срочной необходимости), байт OOB, который в данный момент находится в очереди, может быть потерян, так как он заменяется новым блоком данных OOB (как это происходит в Распространении программного обеспечения Беркли). Однако он никогда не заменяется в потоке данных.
Если SO_OOBINLINE включен, срочные данные остаются в потоке данных. В результате блок данных OOB никогда не теряется при поступлении нового сегмента TCP, содержащего срочные данные. Существующий знак данных OOB обновляется до новой позиции.
Примечание
Если задан параметр сокета SO_OOBINLINE, IOCTL SIOCATMARK всегда возвращает значение TRUE, а данные OOB возвращаются пользователю как обычные данные.