TCP头格式-标记字段-TCP连接状态图-三次握手和四次挥手
参考链接:
TCP与UDP详解
网工面试题(一)
《网络工程师的五天修炼》
《极客专栏-网络排查案例课》
TCP协议特点
TCP协议时一个面向连接的可靠传输协议,具有面向数据流、虚电路连接、有缓冲的传输、无结构的数据流,全双工连接五大特点。TCP段头指示可接收字节数的字段是窗口。TCP采用大小可变的滑动窗口进行流量控制。
TCP的三种机制实现面向连接的服务
1、使用序号对数据进行标记;
2、使用确认、校验、定时器系统提供可靠性;
3、使用窗口机制调整数据流量;
TCP头格式
TCP状态图出处,在 Stevens 的《UNIX 网络编程:套接字联网 API》
SYN_SENT表示请求连接,当要访问的其它计算机服务时,首先要发个同步信号给该端口,此时状态为SYN_SENT,如果连接成功了就变为ESTABLISHED,此时SYN_SENT状态非常短暂。
常用的三个状态是:ESTABLISHED 表示正在通信,TIME_WAIT 表示主动关闭,CLOSE_WAIT 表示被动关闭。
TCP协议规定,对于已经建立的连接,网络双方要进行四次握手才能成功断开连接,如果缺少了其中某个步骤,将会使连接处于假死状态,连接本身占用的资源不会被释放。对于常用服务器而言,最值得注意的状态有两个:CLOSE_WAIT和TIME_WAIT。TIME_WAIT 是主动关闭链接时形成的,等待2MSL时间,约4分钟。主要是防止最后一个ACK丢失。 由于TIME_WAIT的时间会非常长,因此server端应尽量减少主动关闭连接CLOSE_WAIT是被动关闭连接是形成的。根据TCP状态机,服务器端收到客户端发送的FIN,则按照TCP实现发送ACK,因此进入CLOSE_WAIT状态。但如果服务器端不执行close(),就不能由CLOSE_WAIT迁移到LAST_ACK,则系统中会存在很多CLOSE_WAIT状态的连接。
这张图的难点主要是视角不固定,一会是发送方,一会是接收方,对初学者来说很容易混淆。更推荐这个图片:
过程解读如下:
tcp三次握手![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/ef0dcb41a1516a1737945a0afa0a4866.png)
##TCP连接释放机制
TCP释放连接可以分为四步,具体过程如下: 双方通信之前均处于ESTABLISHED状态。 第一步:源主机发送一个释放报文(FIN=1,自身序号SEQ =x),源主机进入FIN-WAIT状态。 第二步:目标主机接收报文后发出确认报文(ACK=1,确认序号ACK=x+1,自身序号SEQ =y),目标主机进入CLOSE-WAIT状态。此时,源主机停止发送数据,但是目标主机仍然可以发送数据,此时TCP连接为半关闭状态(HALF-CLOSE)。源主机接收到ACK报文后等待目标主机发出FIN报文,这可能会持续一段时间。 第三步:目标主机确定没有数据,向源主机发送后,发出释放报文(FIN=1,ACK=1,确认序号ACK =x+1,自身序号SEQ =z)。目标主机进入LAST-ACK状态。 注意:这里由于处于半关闭状态(HALF-CLOSE),目标主机还会发送一些数据,其序号不一定为y+1,因此可设为z。而且,目标主机必须重复发送一次确认序号ACK=x+1。 第四步:源主机接收到释放报文后,对此发送确认报文(ACK=1,确认序号ACK=z+1,自身序号SEQ=x+1),在等待一段时间确定确认报文到达后,源主机进入CLOSED状态。目标主机在接收到确认报文后,也进入CLOSED状态。释放连接的过程如图所示。
TCP连接的关闭流程是,首先由发起方发送一个结束包(将FIN置为1,并提供序号);当应答方收到后,先进行肯定确认(ACK 序号+1),而不急于回送FIN包,先去通知相应的应用程序;当应用程序指示TCP软件彻底关闭时,TCP软件再发送第二个FIN包。其它的过程是与建立连接类似的。
彩蛋:
TCP 里一个报文可以搭另一个报文的顺风车(Piggybacking),以提高 TCP 传输的运载效率。所以,TCP 挥手倒不是一定要四个报文,Piggybacking 后,就可能是 3 个报文了。看起来就类似三次挥手;
相关问题:
1、介绍TCP连接的三次握手?追问:为什么TCP需要握手三次?
2、介绍TCP断开的四次挥手?追问:为什么TCP的挥手需要四次?
3、为什么连接的时候是三次,挥手的时候是四次?
误区:
误区1:一台机器最多 65535 个 TCP 连接
连接是四元组,并不是单纯的源端口或者目的端口。那么多个数相乘,这个乘积当然可以远远超过 65535 了。先不谈论海量级网站的场景,就算我们维护一台 Web 服务器,假如当前有 10 万台客户端连着你,平均每个客户端跟你有 6 个连接(这很常见),那么就是 60 万个连接了,是不是也早就超过 6 万了?
当然,在限定场景下,一个客户端(假设只有一个出口 IP)和一个服务端(假设也只有一个 IP 和一个服务端口),那么确实只能最多发起 6 万多个连接。但你自己也已经明白,这跟前面的误解,已经是两回事了。
误区2:不能同时发起握手
其实,通信双方还真的可以同时向对方发送 SYN,也能建立起连接。你可以参考这节课里我提到的 TCP 状态转换图。在 Richard Stevens 的《TCP/IP 详解(第一卷)》里,也提到了这个知识点,参考下图: