After writing an answer about TCP_NODELAY and TCP_CORK, I realized that my knowledge of TCP_CORK's finer points must be lacking, since it's not 100% clear to me why the Linux developers felt it necessary to introduce a new TCP_CORK flag, rather than just relying on the application to set or clear the existing TCP_NODELAY flag at the appropriate times.
In particular, if I have a Linux application that wants to send() some small/non-contiguous fragments of data over a TCP stream without paying the 200mS Nagle latency-tax, and at the same time minimize the number of packets needed to send it, I can do it either of these two ways:
With TCP_CORK (pseudocode):
int optval = 1;
setsockopt(sk, SOL_TCP, TCP_CORK, &optval, sizeof(int)); // put a cork in it
send(sk, ..);
send(sk, ..);
send(sk, ..);
optval = 0;
setsockopt(sk, SOL_TCP, TCP_CORK, &optval, sizeof(int)); // release the cork
or with TCP_NODELAY (pseudocode):
int optval = 0;
setsockopt(sk, IPPROTO_TCP, TCP_NODELAY, &optval, sizeof(int)); // turn on Nagle's
send(sk, ..);
send(sk, ..);
send(sk, ..);
optval = 1;
setsockopt(sk, IPPROTO_TCP, TCP_NODELAY, &optval, sizeof(int)); // turn Nagle's back off
I've been using the latter technique for years with good results, and it has the benefit of being portable to non-Linux OS's as well (although outside of Linux you have to call send() again after turning Nagle's back off, in order to ensure the packets get sent immediately and avoid the Nagle-delay -- send()'ing zero bytes is sufficient).
Now the Linux devs are smart guys, so I doubt that the above usage of TCP_NODELAY never occurred to them. There must be some reason why they felt it was insufficient, which led them to introduce a new/proprietary TCP_CORK flag instead. Can anybody explain what that reason was?