0

According to the manpage, TCP_CORK prevents sending partials, unsetting it flushes partials. Having TCP_CORK set and setting TCP_NODELAY also flushes partial data. Sounds similar, where exactly lies the difference?

On a connection that has TCP_CORK set:

  1. Is it correct, that TCP_NODELAY flushes at most a single partial packet and afterwards goes back to the TCP_CORK behaviour? (so it's more of an event, than a permanent option!?) (Man page explicitly mentions All queued partial frames are sent when the option is cleared again. How would there be multiple queued partial frames? Wouldn't all partials be coalesced into one packet?)
  2. Can TCP_NODELAY be set repeatedly on a TCP_CORK connection to flush out the pending data? (or would it need to be unset first?)

man tcp:

   TCP_CORK (since Linux 2.2)
          If set, don't send out partial frames.  All queued partial frames are sent when the option is cleared again.  This is useful for prepending headers before calling sendfile(2), or  for
          throughput  optimization.   As  currently  implemented, there is a 200 millisecond ceiling on the time for which output is corked by TCP_CORK.  If this ceiling is reached, then queued
          data is automatically transmitted.  This option can be combined with TCP_NODELAY only since Linux 2.5.71.  This option should not be used in code intended to be portable.
   TCP_NODELAY
          If set, disable the Nagle algorithm.  This means that segments are always sent as soon as possible, even if there is only a small amount of data.  When not set, data is buffered until
          there  is  a  sufficient  amount  to  send out, thereby avoiding the frequent sending of small packets, which results in poor utilization of the network.  This option is overridden by
          TCP_CORK; however, setting this option forces an explicit flush of pending output, even if TCP_CORK is currently set.
Niels-Ole
  • 129
  • 1
  • 9

1 Answers1

0

This is not a real answer, but I thought I share what I got anyways.

I did a little test setup.

Client:

    optval = 1;
    setsockopt(sockfd, IPPROTO_TCP, TCP_CORK, &optval, sizeof(int));
    write(sockfd, "foo\n", 4);
    setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, &optval, sizeof(int));
    usleep(70000);
    write(sockfd, "bar\n", 4);
    setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, &optval, sizeof(int));
    usleep(70000);
    write(sockfd, "hello\n", 6);
    usleep(70000);
    write(sockfd, "world\n", 6);

Server:

# netcat -l 8123 | ts -i "%.S"
17.365721 foo
00.070271 bar
00.140462 hello
00.000216 world

The 70ms delay was chosen to be lower than the 200ms timeout of the TCP_CORK flag.

As you can see, TCP_NODELAY can be used to flush the data repeatedly. (Question number 2 is therefore answered)

Bonus: When looking at the packets on the wire, we can see that when setting TCP_NODELAY, the PSH flag is set on the packet. Thus the data is possibly also flushed on the receiver end. (Compare Difference between push and urgent flags in TCP)

Niels-Ole
  • 129
  • 1
  • 9