聊清楚TCP三次握手四次挥手
目录
前言
TCP:传输控制协议
TCP简介
TCP首部
TCP连接的建立和终止
三次握手
四次挥手
TCP的状态变迁图
2MSL等待状态
FIN_WAIT_2状态
最大报文段长度
TCP的半关闭
两端同时打开
两端同时关闭
复位报文段
前言
上周记录了一下DNS的相关信息,包含DNS服务器的分类、如何利用DNS将域名转换成真实的IP等信息
今天就来记录一下TCP的三次握手四次挥手究竟是怎么样的?以及为什么在四次挥手中会存在TIME_WAIT状态?
TCP:传输控制协议
TCP简介
TCP提供一种面向连接的、可靠的字节流服务。
面向连接是指两个使用TCP的应用在彼此交换数据之前必须先建立一个TCP连接。
其可靠性体现在如下几个方面:
应用数据分片 超时重传 数据接收确认 保持首部和数据的校验和 数据接收后进行重排序 丢弃重复数据 流量控制 拥塞控制
TCP首部
TCP数据依旧是封装在IP数据报中的
TCP首部详细
一个IP地址和一个端口号也称为一个插口,插口对(包含客户端服务端端口号、IP的四元组)可唯一确定互联网络中的每个TCP连接的双方。
序号用来标识从TCP发端向TCP收端发送的数据字节流,它表示在这个报文段中的的第一个数据字节。如果将字节流看作在两个应用程序间的单向流动,则TCP用序号对每个字节进行计数。序号是32bit的无符号数,序号到达232-1后又从0开始。
当新建一个新的连接时,SYN标志变为1
每个传输的字节都被计数,确认序号包含发送确认的一端所期望收到的下一个序号。
确认序号是上次已成功收到数据字节序号加1。(例如第一次传输0~1024,那么确认序号就是1025)只有ACK标志为1025时确认序号字段才有效。
TCP为应用层提供全双工服务。这意味数据能在两个方向上独立地进行传输。
检验和覆盖了整个的TCP报文段TCP首部和TCP数据。这是一个强制性的字段,一定是由发端计算和存储,并由收端进行验证。TCP检验和的计算和UDP检验和的计算相似,使用一个伪首部。
首部长度给出首部中32bit字的数目。需要这个值是因为任选字段的长度是可变的。这个字段占4bit,因此TCP最多有60字节的首部。
URG 紧急指针有效 ACK 确认序号有效。 PSH 接收方应该尽快将这个报文段交给应用层。 RST 重建连接。 SYN 同步序号用来发起一个连接。 FIN 发端完成发送任务
TCP连接的建立和终止
TCP是一个面向连接的协议,无论哪一方向另一方发送数据之前,都必须先在双方之间建立一条连接。
TCP接受一个连接是将其放入队列中,而应用层接受一个连接是将其从该队列中移出。
应用层在三次握手中的第三个报文段收到之后才会知道有新的连接。
建立一条连接需要三次握手,而终止一条连接需要四次握手。
格式:
源 > 目的:标志
第一行中,字段1415531521:1415531521(0)表示分组的序号是1415531521,(0)表示数据字节数为0。
开始的序号:隐含的结尾序号(数据字节数)。显示序号和隐含结尾序号的优点是便于了解数据字节数大于0时的隐含结尾序号,此字段是有在满足条件报文段中至少包含一个数据字节或SYN、FIN或RST被设置为1的时候才显示。
第二行中的ack为1415531522表示确认序号,只有在首部的ACK标志比特为1的时候才显示。
win 4096表示发端通告的窗口大小,没有数据交换,则默认为4096.
<mss 1024>表示由发端指明的最大报文段长度选项,发端将不接收超过此长度的TCP报文段。
三次握手
(1)客户端发送一个SYN段指明客户打算连接的服务器的端口号,以及初始序号(ISN,例如1415531521),这个SYN段为报文段1
(2)服务端发回包含服务端的初始序号的SYN报文段(报文段2)作为应答。同时将确认序号设置为客户端ISN加1以对客户的SYN报文段进行确认,一个SYN将占用一个序号。
(3)客户必须将确认序号设置为服务器的ISN加1以对服务器的SYN报文段进行确认
ESTABLISHED状态是连接双方能进行双向数据传递的状态。
例如:
当一端为建立连接而发送它的SYN时,为连接选择一个初始序号,ISN随时间而变化,因此每个连接都具有不同的ISN。
四次挥手
建立一个连接需要三次握手,终止一个连接需要四次挥手,这是由TCP的半关闭造成的。
既然TCP是全双工的,因此每个方向必须单独的进行关闭。
这原则就是当一方完成它的数据发送任务后就能发送一个FIN来终止这个方向的连接。当一端收到一个FIN,它必须通知应用层另一端几经终止了那个方向的数据传送。发送FIN通常是应用层进行关闭的结果。
首先进行关闭的一方(即发送第一个FIN)将执行主动关闭,而另一方(收到这个FIN)执行被动关闭。通常一方完成主动关闭而另一方完成被动关闭,
当服务器收到这个FIN,它发回一个ACK,确认序号为收到的序号加1(报文段5)。和SYN一样,一个FIN将占用一个序号。同时TCP服务器还向应用程序(即丢弃服 务器)传送一个文件结束符。接着这个服 务器程序就关闭它的连接,导致它的TCP端发送一个FIN(报文段6),客户必须发回 一个确认,并将确认序号设置为收到序号 加1(报文段7)
TCP的状态变迁图
粗的实线箭头表示正常的客户端状态变迁,用粗的虚线箭头表示正常的服务器状态变迁。
整个流程图:
2MSL等待状态
TIME_WAIT状态也称为2MSL等待状态。
每个TCP实现必须选择一个报文段最大生成时间(Maximum Segment Lifetime),是任何报文段在被丢弃前在网络内的最长时间。
RFC 793 [Postel 1981c] 指出MSL为2分钟。然而,实现中的常用值是30秒,1分钟, 或2分钟。
TCP报文段在IP数据报中传输,IP数据报则有存活限制时间TTL字段。
对一个给定的MSL来说,当TCP执行一个主动关闭,并发送最后一个ACK,该连接必须在TIME_WAIT状态停留时间为2倍的MSL,可让TCP再次发送最后的ACK以防这个ACK丢失(另一端超时并重发最后的FIN)。
就比如上述这个图,当服务端发送LAST_ACK的时候,客户端就处于了TIME_WATI状态,此时客户但必须在这个状态保持2MSL时间,为的是客户端在发送最后一个ACK给服务端的时候,服务端在2MSL时间内没收到这个ACK的话,服务端会重新发送LAST_ACK,而之前那个LAST_ACK就被丢弃
这种2MSL等待的另一个结果是这个TCP连接在2MSL等待器间,此连接涉及的四元组(客户端IP、port,服务器IP、port)不能再被使用,只有2MSL结束后才能再被使用。
不过在实际应用中可以通过设置SO_REUSEADDR选项达到不必等待2MSL时间结束再使用此端口。
TIME_WAIT状态的影响:
在高并发的状态下会有大量 time_wait 状态存在,会导致新建 TCP 连接会出错,address already in use : connect 异常
解决方法:
1.客户端,HTTP 请求的头部,connection 设置为 keep-alive,保持存活一段时间:现在的浏览器,一般都这么进行了
2.服务器端允许time_wait状态的socket被重用,缩减time_wait时间,设置为1MSL(即,2 mins)
FIN_WAIT_2状态
客户端已经发出了FIN,并且服务端也已对它进行确认。
只有当另一端的进程完成这个关闭,客户端才会从FIN_WAIT_2状态进入TIME_WAIT状态
最大报文段长度
最大报文段长度(MSS)表示TCP传往另一端的最大块数据的长度,当一个连接建立时,连接的双方都要通告各自的MSS。
MSS字段只能出现在SYN报文段中
如果目的IP地址是非本地的,MSS通常默认值是536。
如何判断是否本地:
(1)网络号和子网号一样,是本地
(2)网络号和子网号都不一样,非本地
(3)网络号一样,子网号不一样,本地非本地都有可能
MSS让主机限制另一端发送数据报的长度,加上主机也能控制它发送数据报的长度,这将使以较小MTU连接到一个网络上的主机避免分段。
一般MSS是MTU减去20字节的IP首部和20字节的TCP首部。
TCP的半关闭
TCP提供了连接的一端在结束它的发送后还能接收来自另一端数据的能力,这就是半关闭。
两端同时打开
需要进行4次握手,比正常多一次
两端同时关闭
复位报文段
TCP首部中的RST比特是用于“复位”的。一般说来,无论何时一个报文。段发往基准的连接( referenced connection)出现错误,TCP都会发出一个复位报文段(这里提到的“基准的连接”是指由目的IP地址和目的端口号以及源IP地址和源端口号指明的连接)。
产生复位的一种常见情况是当连接请求到达时,目的端口没有进程正在听。对于 UDP,当一个数据报到达目的端口时,该端口没在使用,它将产生一个ICMP端口不可达的信息。而TCP则使用复位。
异常终止一个连接,或者检测半打开连接都需要发送一个复位报文段。
往期推荐:
DNS域名解析系统