Problemas de concepção - enviar segmentos de dados pequeno através de TCP com o Winsock

Traduções de Artigos Traduções de Artigos
Artigo: 214397
Expandir tudo | Reduzir tudo

Nesta página

Sumário

Quando necessitar de enviar pacotes de dados pequeno através de TCP, a concepção da aplicação Winsock é especialmente importante. Um design que não toma em consideração a interacção de confirmação adiada, o algoritmo de Nagle e colocação em memória intermédia de Winsock drasticamente pode afectar o desempenho. Este artigo aborda estas questões, utilizando um par de estudos de casos e deriva de uma série de recomendações para o envio de pacotes de dados pequeno de forma eficaz de uma aplicação Winsock.

Mais Informação

Fundo

Quando uma pilha Microsoft TCP recebe um pacote de dados, um temporizador de atraso de 200-ms vai. Quando, eventualmente, é enviada uma confirmação, o temporizador de atraso é reposto e iniciará o atraso de 200-ms outro quando é recebido o seguinte pacote de dados. Para aumentar a eficiência na Internet e as aplicações de intranet, a pilha Microsoft TCP utiliza os seguintes critérios para decidir quando enviar uma confirmação em pacotes de dados recebidos:
  • Se o segundo pacote de dados for recebido antes de expirar o tempo de atraso, a confirmação é enviada.
  • Se existirem dados a enviar na mesma direcção como a confirmação antes do segundo pacote de dados é recebido e o temporizador de atraso expira, a confirmação é piggybacked com o segmento de dados e enviada imediatamente.
  • Quando o temporizador de atraso expira, é enviada a confirmação.
Para evitar ter de pacotes de dados small congest da rede, a pilha Microsoft TCP permite o algoritmo Nagle por predefinição, o que coalesces uma memória intermédia de dados pequeno de várias chamadas a enviar e atrasos de envio que até enviado um ACK para o pacote de dados anterior é recebido do anfitrião remoto. Seguem-se duas excepções para o algoritmo de Nagle:
  • Se a pilha tem coalesced uma memória intermédia de dados maior, a unidade máxima de transmissão (MTU), é imediatamente enviado um pacote inteira sem aguardar confirmação do anfitrião remoto. Numa rede Ethernet, a MTU para TCP/IP é 1460 bytes.
  • A opção de socket TCP_NODELAY é aplicada a desactivar o algoritmo Nagle, de modo a que os pacotes de dados pequenos são entregues com o anfitrião remoto sem demora.
Para optimizar o desempenho na camada de aplicação, Winsock cópias memórias intermédias de dados da aplicação de envio de chamadas a uma memória intermédia de kernel de Winsock. Em seguida, a pilha utiliza própria heurística (por exemplo, o algoritmo de Nagle) para determinar quando efectivamente o pacote na ligação. Pode alterar a quantidade de memória intermédia de kernel do Winsock atribuída ao socket utilizando a opção de SO_SNDBUF (é 8K por predefinição). Se necessário, Winsock pode tampão significativamente mais do que o SO_SNDBUF tamanho da memória intermédia. Na maioria dos casos, a conclusão do envio da aplicação indica apenas a memória intermédia de dados numa aplicação enviar chamada é copiada para a memória intermédia de kernel de Winsock e não indica que os dados atingiu o suporte de rede. A única excepção é quando desactivar a memória intermédia de Winsock, definindo SO_SNDBUF para 0.

Winsock utiliza as seguintes regras para indicar uma conclusão do envio da aplicação (dependendo do modo como é invocada a enviar, a notificação de conclusão poderia ser a função a devolver a partir de uma chamada de bloqueio, um evento de sinalização ou chamar uma função de notificação e assim sucessivamente):
  • Se for o socket ainda no quadro do contingente SO_SNDBUF, Winsock copia os dados a enviar da aplicação e indica a conclusão do envio da aplicação.
  • Se o socket está para além do contingente SO_SNDBUF e existe apenas um envio previamente armazenada em buffer ainda em memória intermédia de kernel de pilha, Winsock copia os dados a enviar da aplicação e indica a conclusão do envio da aplicação.
  • Se o socket está para além do contingente SO_SNDBUF e existir mais do que um previamente armazenada em buffer enviar a memória intermédia de kernel de pilha, Winsock copia os dados a enviar da aplicação. Winsock não indica a conclusão do envio da aplicação até que a pilha completa suficiente envia para colocar o socket novamente dentro do contingente SO_SNDBUF ou apenas uma condição de envio pendentes.

Caso prático 1

Descrição geral:

Necessita de um cliente de Winsock TCP enviar 10000 registos para um servidor de Winsock TCP para armazenar numa base de dados. O tamanho dos registos varia de 20 bytes para 100 bytes de comprimento. Para simplificar a lógica da aplicação, a estrutura é o seguinte:
  • O cliente efectua apenas enviar bloqueio. O servidor faz apenas recv de bloqueio.
  • O socket cliente define a SO_SNDBUF para 0, para que cada registo vai um segmento de dados único.
  • O servidor chama recv num ciclo. A memória intermédia registada no recv é 200 bytes, de modo a que cada registo pode ser recebido no uma receber chamada.

Desempenho:

Durante o ensaio, o programador localiza que o cliente só pode enviar cinco registos por segundo para o servidor. O total de 10000 registos, máximo em 976K bytes de dados (10000 * 100 / 1024), tem mais de meia hora para enviar para o servidor.

Análise:

Uma vez que o cliente não definir a opção de TCP_NODELAY, o algoritmo Nagle força a pilha TCP para aguardar uma confirmação antes de outro pacote pode enviar a ligação. No entanto, o cliente desactivou a memória intermédia de Winsock, definindo a opção de SO_SNDBUF para 0. Por conseguinte, a 10000 enviar chamadas têm de ser enviado e ACK'ed individualmente. Cada confirmação é adiado 200-ms, uma vez que ocorre a seguinte pilha de TCP do servidor:
  • Quando o servidor obtém um pacote, o respectivo temporizador de atraso de 200-ms vai.
  • O servidor não necessita de enviar qualquer coisa, pelo que não pode ser piggybacked a confirmação.
  • O cliente não enviará outro pacote, a menos que o pacote anterior é reconhecido.
  • O temporizador de atraso no servidor expira e é devolvida a confirmação.

Como melhorar o:

Existem dois problemas com esta concepção. Em primeiro lugar, é o problema de temporizador de atraso. O cliente precisa conseguir enviar dois pacotes para o servidor no 200-MS. uma vez que o cliente utiliza o algoritmo Nagle, por predefinição, deverá utilizar apenas a predefinição da memória intermédia de Winsock e não defina SO_SNDBUF como 0. Uma vez que a pilha TCP tem coalesced uma memória intermédia maior para a unidade máxima de transmissão (MTU), é imediatamente enviado um pacote inteira sem aguardar confirmação do anfitrião remoto.

Em segundo lugar, esta estrutura chama um envio para cada registo de tal pequeno tamanho. Enviar este pequeno de um tamanho não é muito eficiente. Neste caso, o programador querer cada registo de 100 bytes de preenchimento e enviar 80 registos ao mesmo tempo um cliente enviar chamada. Para permitir que o servidor sabe quantos registos serão enviados no total, o cliente poderá pretender começar a desactivar a comunicação com um cabeçalho de tamanho de correcção que contém o número de registos a seguir.

Caso prático 2

Descrição geral:

Uma aplicação de cliente Winsock TCP abre duas ligações com uma aplicação de servidor Winsock TCP fornecer o serviço de cotações. A primeira ligação é utilizada como um canal de comando para enviar o símbolo de cotações para o servidor. A segunda ligação é utilizada como um canal de dados para receber a cotação de acções. Depois de tem sido estabelecidas duas ligações, o cliente envia um símbolo de acção para o servidor através do canal de comando e aguarda que a cotação de acções voltar através do canal de dados. Envia o pedido de símbolo de cotações seguinte para o servidor após a recepção da primeira cotação de acções. O cliente e o servidor não definem a opção SO_SNDBUF e TCP_NODELAY.

Desempenho:

Durante o ensaio, o programador localiza que o cliente só é possível obter a cinco propostas por segundo.

Análise:

Esta estrutura permite apenas um pedido de cotação de acções pendentes ao mesmo tempo. O primeiro símbolo das acções é enviado ao servidor através do canal de comandos (ligação) e é enviada uma resposta imediatamente anterior a partir do servidor para o cliente através do canal de dados (ligação). Em seguida, o cliente envia imediatamente o segundo pedido de símbolo de cotações e a enviar devolve imediatamente como a memória intermédia de pedido na chamada de envio é copiada para a memória intermédia de kernel de Winsock. No entanto, a pilha TCP do cliente não é possível enviar o pedido da respectiva memória intermédia de kernel imediatamente porque o primeiro enviar através do canal de comandos não é ainda confirmado. Depois de 200-ms atrasar temporizador no canal de comando de servidor expira, ACK para o primeiro pedido de símbolo for devolvida ao cliente. Em seguida, o segundo pedido de proposta é enviado com êxito para o servidor após a ser adiada para 200-MS. proposta para o símbolo da segunda acção voltar imediatamente através do canal de dados porque, neste momento, o temporizador de atraso do canal de dados do cliente expirou. Um ACK para a resposta da proposta anterior é recebido pelo servidor. (Lembre-se de que o cliente não foi possível enviar um segundo pedido de cotação de acções para 200-ms, dando assim o tempo para o temporizador de atraso no cliente expirar e enviar uma confirmação para o servidor.) Como resultado, o cliente obtém a segunda resposta de proposta e pode emitir outro pedido de proposta, que está sujeita ao mesmo ciclo.

Como melhorar o:

É desnecessário o design de ligação de dois (canal). Se utilizar apenas uma ligação para o pedido de cotação de acções e a resposta, pode ser piggybacked na resposta proposta e voltar imediatamente ACK para o pedido de proposta. Melhorar o desempenho, o cliente poderia "multiplex" vários pedidos de cotação da bolsa numa chamada de envio para o servidor e o servidor foi também "multiplex" várias respostas de proposta numa chamada de enviar ao cliente. Se a estrutura de dois canais unidireccional é realmente necessária por algum motivo, ambos os lados devem definir a opção de TCP_NODELAY para que os pacotes pequenos podem ser enviados imediatamente, sem ter de esperar uma confirmação para o pacote anterior.

Recomendações:

Apesar destes dois estudos de caso são transformados, elas ajudam para ilustrar alguns cenários de casos piores. Quando estrutura uma aplicação que envolve o segmento de dados alargados de pequenas envia e recvs, deverá considerar as seguintes directrizes:
  • Se os dados são segmentos tempo não críticas, a aplicação deverá adesão-los num bloco de dados maior para passar para uma chamada de envio. Uma vez que a memória intermédia de envio é susceptível de ser copiados para a memória intermédia de kernel de Winsock, a memória intermédia não deve ser demasiado grande. Um pouco menos de 8K é normalmente eficaz. Desde que o kernel do Winsock, obtém um bloco maior do que a MTU, irá enviar vários pacotes de tamanho completo e um pacote último com tudo o que é deixado. O lado de envio, excepto o último pacote, não será accionado pelo temporizador de atraso de 200-ms. O último pacote, se acontecer de ser um pacote ímpar, corre ainda o algoritmo de atraso de confirmação. Se a pilha de extremidade de envio obtiver outro bloco maior do que a MTU, ainda pode ignorar ao algoritmo de Nagle.
  • Se possível, evite ligações de socket com fluxo de dados unidireccional. Comunicações através de sockets unidireccionais são mais afectados pelo Nagle e atrasada algoritmos de confirmação facilmente. Se a comunicação segue um pedido e um fluxo de resposta, deverá utilizar um socket único fazer envia e recvs para que a confirmação pode ser piggybacked na resposta.
  • Se tiverem todos os segmentos de dados pequeno para ser enviada imediatamente, defina a opção de TCP_NODELAY na extremidade de envio.
  • A menos que pretenda garantir que um pacote é enviado a ligação quando concluído um envio é indicado pelo Winsock, não deve definir o SO_SNDBUF para zero. De facto, a memória intermédia 8K tenha sido determinada heuristicamente a funcionar bem para a maioria das situações e não deve alterá-la a menos que tenha testado que a nova definição de memória intermédia do Winsock permite um melhor desempenho do predefinido. Além disso, definir SO_SNDBUF para zero é principalmente benéfica para aplicações que em massa de transferência de dados. Mesmo assim, para a máxima eficácia que deve utilizar em conjunto com dupla colocação em memória intermédia (envio pendente mais do que um determinado momento) e sobrepostas e/s.
  • Se a entrega de dados não tem de ser garantida, utilize UDP.

Referências

Para mais informações sobre o atraso de confirmação e o algoritmo de Nagle, consulte o seguinte:

Braden, R. [1989], RFC 1122, requisitos para Internet Hosts--camadas de comunicação, Internet Engineering Task Force.

Propriedades

Artigo: 214397 - Última revisão: 25 de maio de 2013 - Revisão: 4.0
Palavras-chave: 
kbdswnet2003swept kbapi kbinfo kbip kbnetwork kbwinsock kbmt KB214397 KbMtpt
Tradução automática
IMPORTANTE: Este artigo foi traduzido por um sistema de tradução automática (também designado por Machine translation ou MT), não tendo sido portanto revisto ou traduzido por humanos. A Microsoft tem artigos traduzidos por aplicações (MT) e artigos traduzidos por tradutores profissionais. O objectivo é simples: oferecer em Português a totalidade dos artigos existentes na base de dados do suporte. Sabemos no entanto que a tradução automática não é sempre perfeita. Esta pode conter erros de vocabulário, sintaxe ou gramática? erros semelhantes aos que um estrangeiro realiza ao falar em Português. A Microsoft não é responsável por incoerências, erros ou estragos realizados na sequência da utilização dos artigos MT por parte dos nossos clientes. A Microsoft realiza actualizações frequentes ao software de tradução automática (MT). Obrigado.
Clique aqui para ver a versão em Inglês deste artigo: 214397

Submeter comentários

 

Contact us for more help

Contact us for more help
Connect with Answer Desk for expert help.
Get more support from smallbusiness.support.microsoft.com