non blocking socket TCP packet loss

It looks like the send() func in this case is too much faster than recv() and recv() never reach 262144-bytes I don't wanna use blocking sockets as there are many messages that have to be processed by the MsgPoc callback, any idea on how to fix this

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
// peer 1

char buff[262144]; // 265 kb

LRESULT CALLBACK MsgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch (uMsg)
    {
        //...
    case WM_SOCKET:     // #define WM_SOCKET (WM_USER + 1)
        switch (WSAGETSELECTEVENT(lParam))
        {
        case FD_READ:
        {
            nBytes += recv(sock, buff, 262144, 0); // always receiving 5840 bytes max
            fwrite(buff, 1, 262144, file);            
            break;
        }
        //...
    }
    return 0;
}

// peer2 sends packets from the main loop
while (GetMessage(&msg, nullptr, 0, 0))
{
    TanslateMessage(&msg);
    DispatchMessage(&msg);

    fread(buff, 1, 262144, file);
    nBytes += send(sock, buff, 262144, 0);
}
Last edited on
It might help if you knew something about how the internet protocols actually work.

https://en.wikipedia.org/wiki/Maximum_transmission_unit
They're not infinite capacity pipes you can just stuff 'X' bytes in at one end in a single send() call, and instantaneously get 'X' bytes out at the other end in a single corresponding recv() call.

> // always receiving 5840 bytes max
Looks suspiciously close to being an MTU around the 1500 mark, and you getting 4 fragments worth of data before the internal "let's not wait around too long, this is a non-blocking connection" timer kicks in and gives you some of your data.

The operative word being 'some'. You wanted a non-blocking connection, so you get a little and often delivery of your data.

If you want to fill stupid-large-buffer, then you're going to have to wait for it to be filled with a blocking socket. But it won't do you any good. Just saying 'stupid large buffer' doesn't magically speed up the rest of the network to cater for your desires. Do the math, it might take a substantial fraction of a second to fill 256Kb of data on your current network connection.

Both send() and recv() are subject to fragmentation at any point, and it is YOUR problem to solve, not the protocol's problem.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// send
size_t n = fread(buff, 1, sizeof(buff), file);
char *bp = buff;
while ( n > 0 ) {
    ssize_t sent = send(sock,bp,n,0);
    if ( sent > 0 ) {
        n -= sent;
        bp += sent;
    } else {
        // deal with error
        // but EAGAIN / EWOULDBLOCK are special
    }
}

// recv
ssize_t nBytes = recv(sock, buff, sizeof(buff), 0);
if ( nBytes > 0 ) {
    size_t written = fwrite(buff, 1, nBytes, file);
    // check written == nBytes, your disk might be full
} else {
    // deal with error
    // but EAGAIN / EWOULDBLOCK are special
}


See also https://en.wikipedia.org/wiki/Fallacies_of_distributed_computing
Registered users can post here. Sign in or register to post.