Servidor TCP / IP usando IOCP. Ocasional corrupção de dados nos buffers de recebimento

Estou trabalhando em um aplicativo de servidor IOCP TCP / IP.

Eu testei o desempenho (o que parece estar de acordo com os utilitários de teste de taxa de transferência TCP) e agora testei a integridade dos dados - é aqui que estou obtendo alguma "estranheza".

Como teste inicial, decidi que um cliente de teste enviasse um bloco de dados de 1 MB repetidamente, em que esse bloco é apenas uma sequência de números inteiros incrementados um após o outro. A ideia é que eu possa verificar se cada buffer de dados recebido é consistente com nenhum dado ausente nesse buffer, independente de qualquer outro buffer recebido, o que significa que não preciso me preocupar com a ordem em que os threads lidam com os recebimentos concluídos. (para verificar, extraio o primeiro número inteiro no buffer e prossigo, redefino o valor esperado para 0 se encontrar o valor máximo que o cliente envia. Também tenho uma verificação para garantir que os dados recebidos em cada um sejam múltiplos de 4 (como são inteiros de 4 bytes)).

Parece que estou recebendo blocos aleatórios de dados ausentes ocasionalmente dentro de um buffer, os valores aumentam 1 por 1 e, em seguida, haverá um monte ignorado. O código, no entanto, parece bastante simples e não muito. Originalmente, escrevi o teste em Delphi, mas depois de ter esses problemas, reescrevi uma versão no Visual Studio 2010 C ++ e parece ter o mesmo problema (ou pelo menos muito semelhante).

Obviamente, há mais código no sistema real, mas posso reduzi-lo para praticamente isso no thread de trabalho, que apenas lida com os recebimentos concluídos, verifica os dados no buffer e os publica novamente. Depois de aceitar inicialmente a conexão, crio duas estruturas sobrepostas e aloco buffers de 1 MB para cada uma e então chamo o WSARecv para cada uma delas. Eu verifiquei duas vezes, não estou compartilhando acidentalmente o mesmo buffer entre os dois. Em seguida, é basicamente o que é executado reutilizando estes:

DWORD numberOfBytesTransferred = 0;
ULONG_PTR completionKey = NULL;
PMyOverlapped overlapped = nullptr;

while (true)
{
    auto queueResult = GetQueuedCompletionStatus(iocp, &numberOfBytesTransferred, &completionKey, (LPOVERLAPPED *)&overlapped, INFINITE);
    if (queueResult)
    {
        switch (overlapped->operation)
        {
            case tsoRecv:
            {
                verifyReceivedData(overlapped, numberOfBytesTransferred); // Checks the data is a sequence of incremented integers 1 after the other with no gabs
                overlapped->overlapped = OVERLAPPED(); // Reset the OVERLAPPED structure to defaults

                DWORD flags = 0;
                numberOfBytesTransferred = 0;
                auto returnCode = WSARecv(socket, &(overlapped->buffer), 1, &numberOfBytesTransferred, &flags, (LPWSAOVERLAPPED) overlapped, nullptr);
                break;
            }
            default:;
        }
    }
}

Talvez eu não esteja lidando com algum tipo de erro ou informações adicionais no meu teste simples acima? Originalmente, eu tinha um cliente IOCP enviando dados, mas escrevi outro extremamente simples no Delphi usando soquetes de bloqueio Indy. É basicamente uma linha de código uma vez conectada.

while true do
begin
    IdTCPClient.IOHandler.WriteDirect(TIdBytes(BigData), Length(BigData));
end;

Também escrevi outro servidor usando um componente de soquete assíncrono diferente e não detectou problemas com os dados recebidos, como meu exemplo de IOCP acima, pelo menos ainda. Posso postar mais código e, possivelmente, uma versão para compilar, mas pensei em publicar o acima, caso eu tenha perdido algo óbvio. Acho que o uso de um recebimento e um envio por soquete funciona bem, mas entendo que é válido publicar mais de um para melhorar o desempenho.

questionAnswers(2)

yourAnswerToTheQuestion