Artigo: 823764 - Última revisão: quarta-feira, 28 de Fevereiro de 2007 - Revisão: 5.6

Ocorre um desempenho lento quando copia dados para um servidor TCP utilizando um programa de API de sockets do Windows

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 | Reduzir tudo

Sintomas

Quando executa um programa que utiliza a API de sockets do Windows, poderá detectar um desempenho lento quando copia dados para um servidor TCP.

Se efectuar um rastreio de rede com um sniffer de rede como o Microsoft Network Monitor, o servidor TCP envia TCP ACK para o último segmento TCP segmento numa sequência de dados TCP no temporizador de confirmação adiada (também conhecido como o temporizador ACK adiado). Por predefinição, para sistemas operativos Windows, o valor para este temporizador é 200 milissegundos (ms). Um fluxo de dados normal para enviar a 64 quilobytes (KB) de dados é semelhante ao seguinte sequê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

Este problema ocorre devido ao comportamento arquitectura de API de sockets do Windows e Afd.sys. Este problema ocorre caso se verifiquem as seguintes condições:
  • O programa de sockets do Windows utiliza sockets sem bloqueio.
  • Uma chamada único Enviar ou WSASend chamada preenche a memória intermédia enviar toda subjacente do socket.

    Por exemplo, o programa utiliza a função setsockopt de Windows Sockets para alterar a memória intermédia envio de socket de predefinição para 32 KB durante a respectivas rotinas de inicialização de socket:
    setsockopt( sock, SOL_SOCKET, 32768, (char *) &val, sizeof( int ) );
    mais tarde, quando o programa envia dados, emite uma chamada de Enviar ou uma chamada WSASend e envia 64 KB de dados durante cada envio:
    send(socket, pWrBuffer, 65536, 0);
    neste cenário, sempre que o programa emite uma chamada Enviar de 64 KB de dados, o programa devolve um código de erro SOCKET_ERROR se a memória intermédia de socket de 32 KB subjacente é completamente preenchida. Depois de chama a função WSAGetLastError , o programa recebe o código de erro WSAEWOULDBLOCK . A maior parte dos programas utilizam a função de Seleccionar de sockets do Windows para verificar o estado do socket. Neste cenário, a função Seleccionar não regista o socket como gravável até que o cliente recebe o segmento TCP ACK pendente. Por predefinição num ambiente Windows, isto pode demorar desde como 200 ms devido o algoritmo de atraso de confirmação.
  • Servidor TCP confirma todos os segmentos TCP antes do cliente envia o último segmento TCP com o bit de emissão definido.

Como contornar

Para contornar este problema, utilize um dos seguintes métodos.

Método 1: Utilizar sockets de bloqueio

Este problema ocorre apenas com sockets sem bloqueio. Quando utiliza um socket de bloqueio, este problema não ocorre porque o Afd.sys processa a memória intermédia socket diferente. Para mais informações acerca de socket sem bloqueio de bloqueio e programação, consulte a documentação do Microsoft Platform SDK.

Método 2: Criar o tamanho da memória intermédia de envio de socket maiores que o tamanho da memória intermédia de envio do programa

Para modificar a memória intermédia de envio de socket, utilize a função de getsockopt dos sockets do Windows para determinar o tamanho de memória intermédia de envio de socket actual (SO_SNDBUF) e, em seguida, utilizar setsockopt função para definir o socket enviar tamanho da memória intermédia. Quando tiver terminado, o valor SO_SNDBUF tem de ser maior do que o tamanho de memória intermédia do programa enviar, pelo menos, 1 byte.

Modificar a chamada de Enviar ou a chamada WSASend para especificar uma memória intermédia de tamanho inferior ao valor SO_SNDBUF, pelo menos, 1 byte. No exemplo anterior na secção "Causa" deste artigo, foi possível modificar a chamada setsockopt para o seguinte valor,
setsockopt( sock, SOL_SOCKET, 65537, (char *) &val, sizeof( int ) );
ou pode modificar a chamada Enviar o seguinte valor:
send(socket, pWrBuffer, 32767, 0);
também pode utilizar qualquer combinação destes valores.

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

importante Esta secção, método ou tarefa contém passos que indicam como modificar o registo. No entanto, poderão ocorrer problemas graves se modificar o registo de forma incorrecta. Por conseguinte, certifique-se de que segue estes passos cuidadosamente. Criar uma para protecção adicional, cópia de segurança do registo antes de o modificar. Em seguida, pode restaurar o registo se ocorrer um problema. Para obter mais informações sobre como efectuar uma cópia de segurança e restaurar o registo, clique no número de artigo que se segue para visualizar o artigo na Microsoft Knowledge Base:
322756  (http://support.microsoft.com/kb/322756/ ) Como efectuar uma cópia de segurança e restaurar o registo no Windows


Modificar as definições TCP/IP no servidor TCP para reconhecer imediatamente segmentos TCP recebidos. Esta solução alternativa funciona melhor num ambiente com uma instalação de cliente grande base e em que não é possível alterar comportamento do programa. Em cenários onde o servidor TCP remoto é executado num servidor baseado no Windows, tem de modificar o registo do servidor remoto. Para outros sistemas operativos, consulte a documentação do sistema operativo informações sobre como alterar o temporizador de confirmação adiada.

Num servidor com o Windows 2000, siga estes passos:
  1. Inicie o Editor de registo (Regedit.exe).
  2. Localize e, em seguida, clique na seguinte subchave do registo:
    HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces\<Interface GUID>
  3. No menu Editar , clique em Adicionar valor e, em seguida, crie o seguinte valor de registo:

    nome do valor : TcpDelAckTicks
    tipo de dados : REG_DWORD
    dados do valor : 0
  4. Saia do Editor de registo.
  5. Reiniciar o Windows para que esta alteração tenha efeito.
Num servidor com o Windows XP ou Windows Server 2003, siga estes passos:
  1. Inicie o Editor de registo.
  2. Localize e, em seguida, clique na seguinte subchave do registo:
    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 (DWORD Value) .
  4. Nome ao novo valor TcpAckFrequency e atribua-lhe um valor de 1.
  5. Saia do Editor de registo.
  6. Reiniciar o Windows para que esta alteração tenha efeito.

Método 4: Modificar o comportamento de colocação na memória intermédia no Afd.sys para não bloquear sockets

importante Esta secção, método ou tarefa contém passos que indicam como modificar o registo. No entanto, poderão ocorrer problemas graves se modificar o registo de forma incorrecta. Por conseguinte, certifique-se de que segue estes passos cuidadosamente. Criar uma para protecção adicional, cópia de segurança do registo antes de o modificar. Em seguida, pode restaurar o registo se ocorrer um problema. Para obter mais informações sobre como efectuar uma cópia de segurança e restaurar o registo, clique no número de artigo que se segue para visualizar o artigo na Microsoft Knowledge Base:
322756  (http://support.microsoft.com/kb/322756/ ) Como efectuar uma cópia de segurança e restaurar o registo no Windows


Nota Esta chave de registo só está disponível para o Windows Server 2003 com Service Pack 1 e service packs subsequentes.
  1. Clique em Iniciar , escreva regedit.exe e, em seguida, clique em OK .
  2. Localize e, em seguida, clique na seguinte subchave do registo:
    HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\AFD\Parameters
  3. No menu Editar , aponte para Novo e, em seguida, clique em Valor DWORD (DWORD Value) .
  4. Nome ao novo valor NonBlockingSendSpecialBuffering e atribua-lhe um valor de 1.
  5. Saia do Editor de registo.
  6. Reiniciar o Windows para que esta alteração tenha efeito.

Ponto Da Situação

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

Referências

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

A informação contida neste artigo aplica-se a:
  • Microsoft Windows Server 2003 Enterprise Edition
  • Microsoft Windows Server 2003 Standard Edition
  • Microsoft Windows Server 2003 Web Edition
  • Microsoft Windows XP Home Edition
  • Microsoft Windows XP Professional Edition
  • 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 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: 823764  (http://support.microsoft.com/kb/823764/en-us/ )