SOCKET Sending data


Let's say I use winsock send() to send e.g. 500mb in one send. These 500mb, are they all sent to the user even if the user/client/browser only has a buffer size of 3mb? I mean do the "other end" have the option to not receive more than max 3mb at a time even if I send 500mb? Or is all the data sent/received anyway?


Best regards
Volang
Last edited on
You're just going to fail at both ends with that approach.

https://en.wikipedia.org/wiki/OSI_model
So socket to socket is basically level 5 (session) layer in the OSI model. Your buffer has to then work its way down the protocol stack down to the wire to begin it's journey to your peer socket on some other node.

It then has to traverse the network.

$ tracepath www.cplusplus.com
<< snipped for privacy >>
 5:  peer8-et-0-0-2.telehouse.ukcore.bt.net               16.877ms asymm  7 
 6:  ldn-1-a9.uk.eu                                       10.199ms 
 7:  be100-1298.nwk-5-a9.nj.us                            80.027ms 
 8:  be100-1323.bhs-g2-nc5.qc.ca                          88.794ms 
 9:  no reply
10:  be50-7.bhs-3b-a9.qc.ca                               89.925ms 
11:  cplusplus.com                                        83.888ms reached
     Resume: pmtu 1492 hops 11 back 11 

So for me talking to this site, this message travelled through 11 different network nodes.

The path MTU figure tells me that the maximum size of any single packet is 1492 bytes.
https://en.wikipedia.org/wiki/Maximum_transmission_unit

As I'm writing this sentence, the message length below reads 3070, so it's going to be split into at least 3 fragments between my browser and the message board. It could be more, but it won't be less.

So after some small number of 1492 byte sized buffers have filled up somewhere between you and the recipient, things are going to start backing up towards the sender, and that eventually means your code.

So to answer your question, no, you can't just call send() with a 500MB buffer and expect the system to do all the work for you. Fragmentation is something you have to deal with (at both ends).

You need to do something like 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
ssize_t sendInParts(int sockfd, const void *buf, size_t len, int flags) {
    ssize_t result;
    size_t sent = 0;  // the total sent
    char *bp = buf;  // point to the next byte to be sent

    // loop until the whole buffer is sent, or there is some error
    do {
        result = send(sockfd, bp, len, flags);  // send something
        if ( result > 0 ) {
            // some kind of success, advance the progress
            bp += result;
            len -= result;
            sent += result;
        } else if ( result < 0 ) {
            if ( errno == EAGAIN || errno == EWOULDBLOCK ) {
                sleep(1);  // try again after a short while
                continue;
            }
            // all other errno values are probably fatal, but RTFM
        }
        // result = 0 means peer disconnected
    } while ( result > 0 && len > 0 );
    if ( result >= 0 ) result = sent;
    return result;
}


Similarly, at the recv() end, you can't just pass a stupid large buffer and then expect the system to fill that buffer in a single recv() call. It will at best retrieve a few MTU sized buffers from the lower layers of the remote's protocol stack and then return to your code.

See also
https://en.wikipedia.org/wiki/Fallacies_of_distributed_computing
Let's say I use winsock send() to send e.g. 500mb in one send.
You should note that send() just asks to tcp to pass some data into the network. You should check your return code, because it may send some (and not all), then tell you how much it send; in which case, you'll need to put send)_ in a loop to send all data.

These 500mb, are they all sent to the user even if the user/client/browser only has a buffer size of 3mb?
They're sent to the host computer and will sit in the network stack's memory. When your application calls recv(), you specify how much you are prepared to read. The socket library, winsock in your case, will read from the internal buffer into your application buffer, then release what's been read from the internal buffer.

Sending n bytes in one call doesn't mean the other side has to read n bytes in one call.

Think of send() as passing data into one end of a pipe, and recv() taking data out the other end. You don't care about how stuff gets from one end of the pipe to the next. The view is called a data stream, and TCP is a streaming protocol.
Last edited on

Thanks for your replies and happy new year. :)

I think I need to rephrase my question...

If I(the server) send() more than the user(the client) choose to recv(), what amount has been transferred/registered to the client / does the users "data usage" increase with everything I send() or just with everything the client choose to recv()/reads in?


They're sent to the host computer and will sit in the network stack's memory.


Based on this, the answer is: Everything I send?
Last edited on
If I(the server) send() more than the user(the client) choose to recv(), what amount has been transferred/registered to the client
All of it. As I said above, it sits in the client network buffers until read using recv() or until the socket is closed.
All of it.


That means that anyone can easily make my network slow just by sending big packages as soon as we're connected... And I can't control what's coming at me ? Even if I deny the ip address I guess it's possible to keep a server buzy in others ways as well. E.g. if a server is listening, anyone can just send "whatever" my way and the network has to deal with that?

What examples of "network DOS" are manageable and what examples can/should I prevent?


What are you talking about?

(and starting multiple threads on the same issue doesn't do you any favours either)

> That means that anyone can easily make my network slow just by sending big packages as soon as we're connected
No, they'll be sending large amounts of data in many MTU sized packets.

But you have control over the rate at which they arrive.

If you want the sender to stop sending for a short period of time, you stop calling recv() for a short period of time. The network itself will propagate the delay back to the sender.

> What examples of "network DOS" are manageable and what examples can/should I prevent?
Within your application, the only thing you have control over is the number of connections.
Thanks for answers)
Topic archived. No new replies allowed.