TCP / IP-Server mit IOCP. Gelegentliche Datenbeschädigung in Empfangspuffern

Ich habe an einer TCP / IP-IOCP-Serveranwendung gearbeitet.

Ich habe die Leistung getestet (was anscheinend mit den TCP-Durchsatz-Testprogrammen übereinstimmt) und jetzt die Datenintegrität geteste

Als ersten Test habe ich mich dafür entschieden, dass ein Testclient immer wieder einen 1-MB-Datenblock sendet, bei dem es sich nur um eine Folge von Ganzzahlen handelt, die nacheinander inkrementiert werden. Die Idee ist, dass ich überprüfen kann, ob jeder empfangene Datenpuffer mit keinen fehlenden Daten in diesem Puffer übereinstimmt, unabhängig von jedem anderen empfangenen Puffer, was bedeutet, dass ich mir keine Sorgen machen muss, welche Auftragsthreads den abgeschlossenen Empfang behandeln. (Um dies zu überprüfen, extrahiere ich die erste Ganzzahl aus dem Puffer und scanne nach vorne. Setzen Sie den erwarteten Wert auf 0 zurück, wenn der vom Client gesendete Maximalwert erreicht ist. Außerdem wird überprüft, ob die jeweils empfangenen Daten ein Vielfaches von 4 sind.) (da es sich um 4-Byte-Ganzzahlen handelt).

Ich erhalte gelegentlich zufällige Datenblöcke, die in einem Puffer fehlen. Die Werte werden 1 zu 1 erhöht, dann wird ein Haufen übersprungen. Der Code scheint jedoch recht einfach und nicht sehr umfangreich zu sein. Ich habe den Test ursprünglich in Delphi geschrieben, aber nachdem ich diese Probleme hatte, habe ich eine Version in Visual Studio 2010 C ++ umgeschrieben und scheine dasselbe Problem zu haben (oder zumindest sehr ähnlich).

Es gibt offensichtlich mehr Code im realen System, aber ich kann es so ziemlich auf den Worker-Thread reduzieren, der nur die abgeschlossenen Zugriffe verarbeitet, die Daten im Puffer überprüft und sie dann erneut sendet. Nachdem ich die Verbindung zum ersten Mal akzeptiert habe, erstelle ich zwei überlappende Strukturen, weise jedem 1-MB-Puffer zu und rufe dann WSARecv für jeden dieser Puffer auf. Ich habe doppelt überprüft, ob ich nicht versehentlich den gleichen Puffer zwischen den beiden teile. Dann ist das Folgende so ziemlich das, was läuft, wenn man diese wiederverwendet:

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:;
        }
    }
}

Vielleicht behandle ich in meinem einfachen Test oben keine Fehler oder zusätzliche Informationen? Ich hatte ursprünglich einen IOCP-Client, der Daten sendete, schrieb aber einen weiteren extrem einfachen in Delphi, der Indy-Blocking-Sockets verwendete. Es ist im Grunde eine Codezeile, sobald sie verbunden ist.

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

Ich habe auch einen anderen Server mit einer anderen asynchronen Socket-Komponente geschrieben, und es wurden noch keine Probleme mit den empfangenen Daten festgestellt, wie dies in meinem obigen IOCP-Beispiel der Fall ist. Ich kann mehr Code und möglicherweise eine Version zum Kompilieren posten, dachte aber, ich würde das oben Gesagte posten, falls ich etwas Offensichtliches verpasst habe. Ich denke, ein Empfang und ein Versand pro Socket sind in Ordnung, aber es ist meines Erachtens zulässig, mehrere Sockets zu veröffentlichen, um die Leistung zu verbessern.

Antworten auf die Frage(4)

Ihre Antwort auf die Frage