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