tcp fast open分析

1,881 阅读2分钟

背景

在直播首帧优化的过程中,使用到了tcp fast open(简称tfo)。用于减少建连时间。 本文对测试demo进行抓包分析来讲解tfo的功能。

原理讲解

image.png 如上图所示:

  1. 客户端第一次发送数据时,在SYN包中携带数据一起发出,服务器回复的SYN+ACK且带有cookie,客户端再回复ACK,第一次建连完成,且数据已经在SYN包发出。
  2. 当客户端第二次发送数据时,在SYN包中携带数据+cookie一起发出,服务器回SYN+ACK,客户端再次回复ACK,第二次建连完成,且数据已经在SYN包中发出。

配置测试环境

# echo 3 > /proc/sys/net/ipv4/tcp_fastopen

测试代码

tfo需要客户端和服务器的同时支持。服务器代码需要设置TCP_FASTOPEN的socket选项

int qlen=5;
setsockopt(serverSock, SOL_TCP, TCP_FASTOPEN, &qlen, sizeof(qlen));

客户端代码的流程需要注意两点:

  1. 不再需要connect
  2. 使用sendto发送数据,且flags需要设置MSG_FASTOPEN
sendto(clientSock, "Hello\n", 6, MSG_FASTOPEN, (struct sockaddr *)&addr, sizeof(addr));

详细代码,测试方法和pcap文件链接

抓包分析

1. 客户端服务器均开启tfo的情况

第一个SYN包中开启了tfo且携带了cookie,一些资料中介绍cookid是服务器生成的,但是在此抓包看是客户端生成的。

image.png

图中可以看到tfo选项共10个字节,Kind占用了1个字节,length占用了1个字节,cookie占用了8个字节。 kind是34,length是10。 同时可以看到SYN包中携带了数据。

顺便在在此贴出tcp常见的扩展选项的kind值。image.png

第二个SYN包中截图如下,可以看到cookie值一模一样。

image.png

完整的wireshark分析图如下,可以看到一共有12个数据包。

image.png

2. 客户端开启tfo但服务器不开启tfo的情况

第一个SYN包和上述中一模一样,且cookie都一样,且也携带了数据,但是服务器不支持tfo,所以也就当作普通的SYNC包处理了。在客户端第三次握手的时候在ACK中又携带了数据,此时服务端才接受了数据。如下图:

image.png 可以观察到一共有14个包,多出的两个包就是3号和10号的[PSH,ACK]包。 在此情况下,数据也被发送了两次,浪费带宽。