我们知道一般网络通信协议为了标明协议类型会设计成”头-长度-校验-内容“的结构,特别在TCP粘包场景下,我们必须在应用层协议将数据进行区分。

在使用一些协议通讯的时候,比如Telnet,会有一个字节字节的发送的情景,每次发送一个字节的有用数据,就会产生41个字节长的分组,20个字节的IP Header和 20个字节的TCP Header,这就导致了1个字节的有用信息要浪费掉40个字节的头部信息,这是一笔巨大的字节开销,而且这种小数据包在广域网上会增加拥塞的出现。

于是为了避免这种情况,一般会考虑将数据延迟发送——即攒一批发一波。这样可以减少IP HeaderTCP Header在整条数据中的比重。

参考纳格算法|WIKI,其逻辑伪代码是:

if 需要发送新数据
   if 窗口大小 >= MSS and 可发送数据大小 >= MSS
     立刻发送MSS大小的数据片段
   else
    if 管道中有未确认的数据
      在下一个ACK收到前,将数据添加到队列
    else
      立刻发送数据

当我们传递的数据包较大,一般来说是不会受到Nagle算法影响。但假如我们使用了小包场景,如心跳、体积小的控制数据等,为了降低延时,我们通常会选择关闭Nagle算法:

int optval = 1;
setsocketopt(fd, IPPROTO_TCP, TCP_NODELAY, &optval, sizeof(optval));