网络程序一般分为客户端和服务端。 首先,让我们用伪代码看看客户端和服务器端程序将调用哪个函数
服务器端:
server((intlistenfd=socket ) pf_inet,SOCK_STREAM,0 );//创建套接字绑定(listenfd,serveraddr,sizeof ) serveraddr; //绑定本地地址和端口的listen(listenq ); //开始侦听//while () client FD=accept (listenfd,clientaddr,clientaddrlen ) )0 //建立连接)//连接成功后,clientfdread /
客户端((intclientfd=socket ) pf_inet,SOCK_STREAM,0 ); //创建socket if (connect (client FD,serveraddr,serveraddrlen )=0)//建立连接)//连接成功后clientFDwrite/read )客户端} } TCP的三次握手是上述函数调用,更准确地说,隐藏在connect和accept之间。 这里借用UNP中3次握手过程的说明:
让我解释一下上图:
1 .在服务器端绑定端口并开始监听时,它会调用accept来等待连接,并且程序会阻止accpet调用
2 .当客户端调用connect时,内核协议栈将syn包发送到服务器端,阻止connect调用。 此时,假设syn数据包的数据包号码为j
3 .当服务器端接收到syn包时,协议栈返回syn包k和到客户端的确认包ack。 将包编号加1将返回syn k和ack j 1
4 .客户端接收到syn k和ack j 1后,响应服务器端的同步包syn k返回确认包ack j 1; 同时,connect函数不再被阻止,并返回到客户端程序。 此时,客户端认为已建立连接
5 .当服务器端程序接收到ack k 1时,将返回accept函数。 此时,三次握手结束了。
想想TCP为什么需要三次握手吧。 实际上,握手3次的场景是互相对话确认对方存在的过程。
A:你听过我说话吗? (SYN )
b :我听到了。 你能听到我说话吗? (ACK SYN )
A:我也能听到(ACK ) )。
好的,握手结束了
如果这个对话过程缺少一个字,你会发现它不能保证通信链路的双向畅通。
到此为止,我还想提到谷歌近年来提出的TFO(TCPfastopen )。 TFO允许在握手期间携带数据,谷歌应该对http的大面积APP场景改进了tcp。 毕竟是一个http的短连接,三次握手占用了相当长的时间。 我自己对TFO也不太了解,所以只能大致谈谈个人的理解,如果有偏差的话,请谅解。
上述与普通TCP的三次握手只是为了确认对方是否在。 TFO的对话场景大致是这样的:
A:幽默的刺猬,我是yxdfh。 你现在在哪里(sync data )
是B:yxdfh吧。 我是一只幽默的刺猬。 我在0.98零时酒吧。 (同步确认数据) )。
根据以上说明,可以看到TFO在发送sync包的同时,还附加了一些数据。 熟悉http的学生也会注意到,TFO简直就是将一个http请求融合到三次握手中,减少了一个RRT。 根据谷歌的测试,TFO可以将http传输延迟减少15%,所有页面的下载时间平均缩短10%,最多可缩短40%。
关于TFO的更详细的介绍请参考这篇文章