Compartilhar via


Protocol-Independent dados fora de banda

A abstração do soquete de fluxo inclui a noção de dados OOB (fora de banda). Muitos protocolos permitem que partes de dados de entrada sejam marcadas como especiais de alguma forma, e esses blocos de dados especiais podem ser entregues ao usuário fora da sequência normal. Os exemplos incluem dados agilizados no X.25 e em outros protocolos OSI e dados urgentes no uso de TCP pelo BSD UNIX. A seção a seguir descreve o tratamento de dados OOB de maneira independente do protocolo. Uma discussão sobre os dados OOB implementados usando dados urgentes do TCP segue a explicação independente do protocolo. Em cada discussão, o uso do recv também implica recvfrom, WSARecv e WSARecvFrom e referências a WSAAsyncSelect também se aplicam a WSAEventSelect.

Dados OOB independentes do protocolo

Os dados OOB são um canal de transmissão logicamente independente associado a cada par de soquetes de fluxo conectados. Os dados OOB podem ser entregues ao usuário independentemente dos dados normais. A abstração define que os recursos de dados OOB devem dar suporte à entrega confiável de pelo menos um bloco de dados OOB por vez. Esse bloco de dados pode conter pelo menos um byte de dados e pelo menos um bloco de dados OOB pode estar pendente de entrega ao usuário a qualquer momento. Para protocolos de comunicação que dão suporte à sinalização em banda (como TCP, em que os dados urgentes são entregues em sequência com os dados normais), o sistema normalmente extrai os dados OOB do fluxo de dados normal e os armazena separadamente (deixando uma lacuna no fluxo de dados normal). Isso permite que os usuários escolham entre receber os dados OOB na ordem e recebê-los fora da sequência sem precisar armazenar em buffer todos os dados intermediários. É possível espiar os dados fora de banda (OOB).

Um usuário pode determinar se algum dado OOB está aguardando para ser lido usando a função ioctlsocket ou WSAIoctl com o IOCTL SIOCATMARK . Para protocolos em que o conceito da posição do bloco de dados OOB dentro do fluxo de dados normal é significativo, como o TCP, um provedor de serviços do Windows Sockets mantém um marcador conceitual indicando a posição do último byte de dados OOB dentro do fluxo de dados normal. Isso não é necessário para a implementação das funções ioctlsocket ou WSAIoctl que dão suporte a SIOCATMARK. A presença ou ausência de dados OOB é necessária.

Para protocolos em que o conceito da posição do bloco de dados OOB dentro do fluxo de dados normal é significativo, um aplicativo pode processar dados fora de banda embutidos, como parte do fluxo de dados normal. Isso é obtido definindo a opção de soquete SO_OOBINLINE com a função setsockopt . Para outros protocolos em que os blocos de dados OOB são verdadeiramente independentes do fluxo de dados normal, tentar definir SO_OOBINLINE resulta em um erro. Um aplicativo pode usar a função ioctlsocket ou WSAIoctl com o IOCTL SIOCATMARK para determinar se há dados OOB não lidos anteriores à marca. Por exemplo, ele pode usar essas informações para ressincronizar com seu par, garantindo que todos os dados até a marca no fluxo de dados sejam descartados quando apropriado.

Com SO_OOBINLINE desabilitado (a configuração padrão):

  • O Windows Sockets notifica um aplicativo de um evento FD_OOB, se o aplicativo registrado para notificação com WSAAsyncSelect, exatamente da mesma forma que FD_READ é usado para notificar a presença de dados normais. Ou seja, FD_OOB é postado quando os dados OOB chegam sem dados OOB previamente enfileirados. O FD_OOB também é postado quando os dados são lidos usando o sinalizador MSG_OOB enquanto alguns dados OOB permanecem na fila após o retorno da operação de leitura. FD_READ mensagens não são postadas para dados OOB.
  • O Windows Sockets retorna de select com o soquete exceptfds apropriado definido se os dados OOB estiverem na fila no soquete.
  • O aplicativo pode chamar recv com MSG_OOB para ler o bloco de dados urgente a qualquer momento. O bloco de dados OOB pula a fila.
  • O aplicativo pode chamar recv sem MSG_OOB para ler o fluxo de dados normal. O bloco de dados OOB não aparece no fluxo de dados com dados normais. Se os dados OOB permanecerem após qualquer chamada para recv, o Windows Sockets notificará o aplicativo com FD_OOB ou com exceptfds ao usar select.
  • Para protocolos em que os dados OOB têm uma posição dentro do fluxo de dados normal, uma única operação recv não abrange essa posição. Um recv retorna os dados normais antes da marca e um segundo recv é necessário para começar a ler dados após a marca.

Com SO_OOBINLINE habilitado:

  • FD_OOB mensagens não são postadas para dados OOB. Os dados OOB são tratados normalmente para fins das funções select e WSAAsyncSelect e indicados definindo o soquete em readfds ou enviando uma mensagem FD_READ respectivamente.
  • O aplicativo não pode chamar recv com o sinalizador MSG_OOB definido para ler o bloco de dados OOB. O código de erro WSAEINVAL é retornado.
  • O aplicativo pode chamar recv sem o sinalizador MSG_OOB definido. Todos os dados OOB são entregues em sua ordem correta dentro do fluxo de dados normal. Os dados OOB nunca são misturados com dados normais. Deve haver três solicitações de leitura para passar pelos dados do OOB. O primeiro retorna os dados normais antes do bloco de dados OOB, o segundo retorna os dados OOB, o terceiro retorna os dados normais após os dados OOB. Em outras palavras, os limites do bloco de dados OOB são preservados.

A rotina WSAAsyncSelect é particularmente adequada para lidar com a notificação da presença de dados fora da banda quando SO_OOBINLINE está desativado.

Dados OOB no TCP

Importante

A discussão a seguir sobre dados fora de banda (OOB), implementada usando dados urgentes do TCP, segue o modelo usado na distribuição de software de Berkeley. Os usuários e implementadores devem estar cientes de que:

 

  • Há, no momento, duas interpretações conflitantes do RFC 793 (em que o conceito é introduzido).

  • A implementação de dados OOB na Distribuição de Software de Berkeley (BSD) não está em conformidade com os Requisitos de Host especificados no RFC 1122.

    Especificamente, o ponteiro urgente TCP no BSD aponta para o byte após o byte de dados urgente e um ponteiro urgente TCP compatível com RFC aponta para o byte de dados urgente. Como resultado, se um aplicativo enviar dados urgentes de uma implementação compatível com BSD para uma implementação compatível com RFC 1122, o receptor lerá o byte de dados urgente incorreto (ele lê o byte localizado após o byte correto no fluxo de dados como byte de dados urgente).

    Para minimizar problemas de interoperabilidade, os gravadores de aplicativos são aconselhados a não usar dados OOB, a menos que isso seja necessário para interoperar com um serviço existente. Os fornecedores do Windows Sockets são instados a documentar a semântica OOB (BSD ou RFC 1122) que seu produto implementa.

A chegada de um segmento TCP com o conjunto de sinalizadores URG (para urgente) indica a existência de um único byte de dados OOB no fluxo de dados TCP. O bloco de dados OOB tem um byte de tamanho. O ponteiro urgente é um deslocamento positivo do número de sequência atual no cabeçalho TCP que indica o local do bloco de dados OOB (ambíguo, conforme observado no anterior). Ele pode, portanto, apontar para dados que ainda não foram recebidos.

Se SO_OOBINLINE estiver desabilitado (o padrão) quando o segmento TCP que contém o byte apontado pelo ponteiro urgente chegar, o bloco de dados OOB (um byte) será removido do fluxo de dados e armazenado em buffer. Se um segmento TCP subsequente chegar com o conjunto de sinalizadores urgente (e um novo ponteiro urgente), o byte OOB atualmente enfileirado poderá ser perdido à medida que for substituído pelo novo bloco de dados OOB (como ocorre na Berkeley Software Distribution). No entanto, ele nunca é substituído no fluxo de dados.

Com SO_OOBINLINE habilitado, os dados urgentes permanecem no fluxo de dados. Como resultado, o bloco de dados OOB nunca é perdido quando um novo segmento TCP chega contendo dados urgentes. A marca de dados OOB existente é atualizada para a nova posição.

Observação

Quando a opção de soquete SO_OOBINLINE é definida, o IOCTL SIOCATMARK sempre retorna TRUE e os dados OOB são retornados ao usuário como dados normais.