ID do artigo: 823764 - Última revisão: quarta-feira, 28 de fevereiro de 2007 - Revisão: 5.6

Desempenho lento ocorre quando você copia dados para um servidor TCP usando um programa de API do Windows Sockets

Dica do SistemaEste artigo aplica-se a um sistema operativo diferente do que está a utilizar. Foi desactivado o conteúdo do artigo, que pode não ser relevante para si.

Nesta página

Expandir tudo | Recolher tudo

Sintomas

Quando você executa um programa que usa a API do Sockets do Windows, você enfrenta um desempenho lento quando você copia dados para um servidor TCP.

Se você fizer um rastreamento de rede com um sniffer, como Microsoft Network Monitor de rede, o servidor TCP envia uma ACK TCP para o último segmento segmento TCP em um fluxo de dados TCP no timer de confirmação de recebimento atrasado (também conhecido como o cronômetro ACK atrasado). Por padrão, para sistemas operacionais Windows, o valor para este timer é 200 milissegundos (ms). Um fluxo de dados típico para envio de 64 quilobytes (KB) de dados é semelhante à seguinte seqüência: bytes
Client->Server 1460 bytes
Client->Server 1460 bytes
Server->Client ACK
Client->Server 1460 bytes
Client->Server 1460 bytes
Server->Client ACK
....
Client->Server 1460 bytes
Client->Server 1460 bytes
Server->Client ACK-PUSH
Client->Server 1296 bytes
-> delayed ACK 200 ms


Causa

Esse problema ocorre devido ao comportamento arquitetura da API do Windows Sockets e Afd.sys. Esse problema ocorre se todas as seguintes condições forem verdadeiras:
  • O programa de Windows Sockets usa soquetes sem bloqueio.
  • Uma chamada única Enviar ou chamada WSASend preenche o buffer de envio soquete todo subjacente.

    Por exemplo, o programa usa a função de setsockopt Windows Sockets para alterar o buffer de envio padrão soquete para 32 KB durante suas rotinas de inicialização de soquete:
    setsockopt( sock, SOL_SOCKET, 32768, (char *) &val, sizeof( int ) );
    posteriormente, quando o programa envia dados, ele emite uma chamada de Enviar ou uma chamada WSASend e envia 64 KB de dados durante cada envio:
    send(socket, pWrBuffer, 65536, 0);
    nesse cenário, cada vez que o programa emite uma chamada Enviar de 64 KB de dados, o programa retorna um código de erro SOCKET_ERROR se o buffer de 32 KB soquete subjacente é completamente preenchido. Depois que ele chama a função WSAGetLastError , o programa recebe o código de erro WSAEWOULDBLOCK . A maioria dos programas use a função de Selecionar Windows Sockets para verificar o status do soquete. Nesse cenário, a função Selecione não informa o soquete como gravável até que o cliente recebe o segmento ACK TCP pendente. Por padrão em um ambiente Windows, isso pode levar até 200 ms devido o algoritmo confirmação atrasada.
  • O servidor remoto TCP confirma todos os segmentos TCP antes do cliente envia o último segmento TCP com o conjunto de bits de envio.

Como Contornar

Para solucionar esse problema, use qualquer um dos seguintes métodos.

Método 1: Usar bloqueio Sockets

Esse problema ocorre apenas com soquetes sem bloqueio. Quando você usa um soquete de bloqueio, esse problema não ocorre porque o Afd.sys lida com o buffer de soquete diferente. Para obter mais informações sobre soquete sem bloqueio e bloqueio de programação, consulte a documentação do Microsoft Platform SDK.

Método 2: Verifique o tamanho do buffer enviar soquete maiores que o tamanho do buffer de envio de programa

Para modificar o buffer de envio de soquete, use a função de getsockopt Windows Sockets para determinar o tamanho atual de buffer de envio do soquete (SO_SNDBUF) e, em seguida, usar setsockopt função para definir o soquete enviar tamanho do buffer. Quando tiver terminado, o valor SO_SNDBUF deve ser maior que o tamanho de buffer programa envio pelo menos 1 byte.

Modificar a chamada de Enviar ou a chamada WSASend para especificar um buffer de tamanho menor que o valor SO_SNDBUF pelo menos 1 byte. No exemplo anterior da seção "Causa" deste artigo, você poderia modificar ao seguinte valor,
setsockopt( sock, SOL_SOCKET, 65537, (char *) &val, sizeof( int ) );
ou você poderia modificar a chamada Enviar para o seguinte valor:
send(socket, pWrBuffer, 32767, 0);
você também pode usar qualquer combinação desses valores.

Método 3: Modificar as configurações de TCP/IP no servidor de TCP

importante Esta seção, método ou tarefa contém etapas que informam sobre como modificar o registro. No entanto, sérios problemas poderão ocorrer se você modificar o registro incorretamente. Por isso, certifique-se que você execute essas etapas cuidadosamente. Para proteção adicional, fazer backup do registro antes de modificá-lo. Em seguida, você pode restaurar o registro se ocorrer um problema. Para obter mais informações sobre como fazer backup e restaurar o registro, clique no número abaixo para ler o artigo na Base de dados de Conhecimento da Microsoft:
322756  (http://support.microsoft.com/kb/322756/ ) Como fazer backup e restaurar o registro no Windows


Modificar as configurações TCP/IP no servidor TCP para confirmar imediatamente entrados segmentos TCP. Esta solução alternativa funciona melhor em um ambiente que tem uma base de instalação de cliente grandes e onde você não pode alterar o comportamento do programa. Para cenários em que o servidor TCP remoto é executado em um servidor baseado no Windows, você deve modificar o registro do servidor remoto. Para outros sistemas operacionais, consulte documentação do sistema operacional para obter informações sobre como alterar o timer de confirmação atrasada.

Em um servidor que executa o Windows 2000, execute estas etapas:
  1. Inicie o Editor do Registro (Regedit.exe).
  2. Localize e, em seguida, clique na seguinte subchave do Registro:
    HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces\<Interface GUID>
  3. No menu Editar , clique em Adicionar valor e crie o seguinte valor do Registro:

    nome do valor : TcpDelAckTicks
    tipo de dados : REG_DWORD
    dados do valor : 0
  4. Feche o Editor do Registro.
  5. Reinicie o Windows para que essa alteração tenha efeito.
Em um servidor que executa o Windows XP ou Windows Server 2003, execute essas etapas:
  1. Inicie o Editor do Registro.
  2. Localize e, em seguida, clique na seguinte subchave do Registro:
    HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces\<Interface GUID>
  3. No menu Editar , aponte para novo e, em seguida, clique em Valor DWORD .
  4. Nomeie o novo valor TcpAckFrequency e atribuir um valor de 1 a ela.
  5. Feche o Editor do Registro.
  6. Reinicie o Windows para que essa alteração tenha efeito.

Método 4: Modificar o comportamento de buffer no Afd.sys para soquetes sem bloqueio

importante Esta seção, método ou tarefa contém etapas que informam sobre como modificar o registro. No entanto, sérios problemas poderão ocorrer se você modificar o registro incorretamente. Por isso, certifique-se que você execute essas etapas cuidadosamente. Para proteção adicional, fazer backup do registro antes de modificá-lo. Em seguida, você pode restaurar o registro se ocorrer um problema. Para obter mais informações sobre como fazer backup e restaurar o registro, clique no número abaixo para ler o artigo na Base de dados de Conhecimento da Microsoft:
322756  (http://support.microsoft.com/kb/322756/ ) Como fazer backup e restaurar o registro no Windows


Observação Essa chave do Registro só está disponível para Windows Server 2003 com Service Pack 1 e service packs posteriores.
  1. Clique em Iniciar , digite regedit.exe e, em seguida, clique em OK .
  2. Localize e, em seguida, clique na seguinte subchave do Registro:
    HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\AFD\Parameters
  3. No menu Editar , aponte para novo e, em seguida, clique em Valor DWORD .
  4. Nomeie o novo valor NonBlockingSendSpecialBuffering e atribuir um valor de 1 a ela.
  5. Feche o Editor do Registro.
  6. Reinicie o Windows para que essa alteração tenha efeito.

Situação

A Microsoft confirmou que este é um problema nos produtos da Microsoft listados na seção "Aplica-se a".

Referências

328890  (http://support.microsoft.com/kb/328890/ ) Nova entrada do Registro para controlar o comportamento de confirmação (ACK TCP) no Windows XP e no Windows Server 2003

A informação contida neste artigo aplica-se a:
  • Microsoft Windows Server 2003, Enterprise Edition (32-bit x86)
  • Microsoft Windows Server 2003, Standard Edition (32-bit x86)
  • Microsoft Windows Server 2003, Web Edition
  • Microsoft Windows XP Home Edition
  • Microsoft Windows XP Professional
  • Microsoft Windows 2000 Advanced Server
  • Microsoft Windows 2000 Professional Edition
  • Microsoft Windows 2000 Server
  • Windows Server 2008 Datacenter without Hyper-V
  • Windows Server 2008 Enterprise without Hyper-V
  • Windows Server 2008 for Itanium-Based Systems
  • Windows Server 2008 Standard without Hyper-V
  • Windows Server 2008 Datacenter
  • Windows Server 2008 Enterprise
  • Windows Server 2008 Standard
  • Windows Web Server 2008
Palavras-chave: 
kbmt kbprb KB823764 KbMtpt
Tradução automáticaTraduçã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 traduzido ou revisto por pessoas. A Microsoft possui artigos traduzidos por aplicações (MT) e artigos traduzidos por tradutores profissionais, com o objetivo de oferecer em português a totalidade dos artigos existentes na base de dados de suporte. No entanto, a tradução automática não é sempre perfeita, podendo conter erros de vocabulário, sintaxe ou gramática. A Microsoft não é responsável por incoerências, erros ou prejuízos ocorridos em decorrência da utilização dos artigos MT por parte dos nossos clientes. A Microsoft realiza atualizações freqüentes ao software de tradução automática (MT). Obrigado.
Clique aqui para ver a versão em Inglês deste artigo: 823764  (http://support.microsoft.com/kb/823764/en-us/ )