TCP / IP server using IOCP. Accidental data corruption in receive buffers

I was working on a TCP / IP IOCP server application.

I tested the performance (which is similar to the utility for testing TCP throughput), and now we check the integrity of the data - this is where I get some "weirdness".

As an initial test, I decided that the test client again and again sends a 1 MB data block, where this block is a sequence of sequences increasing one after another. The idea is that I can verify that each received data buffer is consistent with missing data in this buffer, regardless of any other received buffer, that is, I do not have to worry about which order flows process completed requests. (to check, I extract the first integer in the buffer and scan ahead, reset the expected value is 0 if I encounter the maximum value that the client sends. I also have a check to make sure the data received in each of them, are plural of 4 (since they are 4 byte integers)).

It seems that I accidentally get random data blocks due to the buffer, the values ​​will grow by 1 by 1, then the bundle will be skipped. The code, although it seems pretty simple and not very. I originally wrote a test in Delphi, but after these problems, I rewrote the version in Visual Studio 2010 C ++ and seemed to have the same problem (or at least very similar).

There is clearly more code in the real system, but I can bring it to a significant number in the workflow, which simply processes the completed requests, checks the data in the buffer, and then publishes them again. After I initially accept the connection, I create two overlapping structures and allocate 1 MB of buffer for each, and then call WSARecv for each of them. I double-checked that I accidentally did not share the same buffer between them. Then, basically, repeats their use:

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

, - ? IOCP, , Delphi, Indy. .

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

, , , IOCP, . , , , , , - . , , , , .

+3
2

, - , , WSASend WSARead. , ( ). MSDN , , , , - ( , ). , , .

, , - , . , WSASend WSARecv , .

, , .

+1

. , , . .

-1

Source: https://habr.com/ru/post/1570179/


All Articles