TCP连接的建立与释放

概述

  • TCP是一个面向连接的协议。无论哪一方向另一方发送数据前,都必须先在双方之间建立一条连接。
  • 这种两端间连接的建立与无连接协议如UDP不同。一端使用UDP向另一端发送数据报时,无需任何预先的握手。

建立连接

三次握手

在这里插入图片描述

  • ack:ack的值表示期望对方下一次发的报文从ack的值开始。

客户三次握手过程如下

  1. 客户端进程向服务器进程发出连接请求,请求报文端首部中的控制位标志SYN=1,由于是首次请求建立连接,因此,控制位标志ACK=0,该报文段包含计算机随机生成的初始序列号seq=x。发送请求连接的TCP报文段,此时客户端进程处于SYN_SENT状态,这是 TCP连接的第一次握手。
  2. 服务端收到客户端发来的请求报文后,若同意建立连接,则向客户端发送确认。确认报文中的控制位SYN=1,ACK=1,确认应答号ack=x+1(即在接收到的序号值基础上加1),并且发送主机的一个初始序列号seq=y(即请求与客户端连接)。此时,服务器端进入SYN_RCVD状态,这是TCP连接的第二次握手。
  3. 客户端进程收到服务端进程的确认报文后,还要想服务端发出确认信息。确认报文段的控制位ACK=1,确认应答号ack=y+1(即在接收到的序列号值基础上加1),此时客户端进入ESTABLISHED状态。这是TCP连接的第三次握手。此时,TCP连接成功建立。

同时打开连接请求

正常情况下,通信一方请求建立连接,另一方被动响应该请求,但是如果出现,通信双方同时请求连接时(两个应用程序同时互相发起发文连接),则连接建立过程并不是三次握手过程。同时打开连接时,两边几乎同时发送SYN,并进入SYN_SENT状态,当每一端收到SYN时,状态都变为SYN_RCVD,同时双方都在发送SYN和ACK作为对收到的SYN进行确认应答。当双方都收到SYN及相应的ACK时,状态均变为ESTABLISHED。
在这里插入图片描述

连接释放

四次挥手

  • 建立一个连接需要三次握手,而终止一个连接要经过4次挥手。这由TCP的半关闭(half-close)造成的。既然一个TCP连接是全双工(即数据在两个方向上能同时传递),因此每个方向必须单独第进行关闭。这原则就是当一方完成它的数据发送任务后就发送一个FIN来终止这个方向连接。当一端接收到一个FIN,它必须通知应用层另一端已经终止了那个方向的数据传送。发送FIN通常是应用层进行关闭的结果。
  • 收到一个FIN只意味在这一方向上没有数据流动。一个TCP连接在收到一个FIN后仍能发送数据。而这对利用半关闭的应用来说是可能的,尽管在实际应用中只有很少的TCP应用程序这样做。
  • 首先进行关闭的一方(即发送第一个FIN)将执行主动关闭,而另一方(收到FIN)执行被动关闭。通常一方完成主动关闭而另一方完成被动关闭。
  • 关闭一边的连接其实只是关闭的一方不在发送带数据的包,ack还是可以发送的。
    总之,由于TCP连接时全双工的,因此每个方向都必须单独进行关闭。原则是主动关闭的一方发送一个FIN报文来表示终止这个方向的连接,收到一个FIN意味着这个方向不再有数据流动,但是另一个方向仍能发送数据,直到另一个方向也发送FIN报文。TCP连接释放的过程如下:
    在这里插入图片描述

四次挥手过程

  1. 客户端进程主动向服务端发出连接释放请求报文,并停止发送数据,主动关闭TCP连接。释放连接报文段控制位FIN=1,系列号seq=i,发送该报文段进入FIN_WAIT_1(终止等待1)状态,等待服务器确认。这是TCP连接释放的第一次挥手。
  2. 服务器收到连接释放请求报文段后即发出确认释放连接的报文段,该报文段控制位ACK=1,确认号为ack=i+1,然后服务器进入CLOSE_WAIT(关闭等待)状态。此时TCP处于半关闭状态,即客户端已经不向服务器发送数据,但服务器仍可向客户端发送数据。这是TCP连接释放的第二次挥手。
  3. 客户端收到服务器的确认信息后,就进入了FIN_WAIT_2(终止等待2)状态,等待服务器发出连接释放请求报文段,若没有数据需要传输,服务器主动向客户端发出连接释放请求报文段,报文段控制位FIN=1,序号seq=j,此时服务器进入LAST_ACK(最后确认)状态,等待客户端的确认应答,这是TCP连接释放的第三次挥手。
  4. 客户端收到服务器的连接释放请求后,必须对此发出确认。确认报文段中控制位ACK=1,确认应答号ack=j+1,客户端发出确认应答消息后进入TIME_WAIT时间等待)状态。在这段时间内TCP连接并没有释放,必须等待2MSL时间后,客户端才进入CLOSED状态。服务器收到客户端的确认应答后,就进入CLOSED状态。直到客户端和服务器都进入CLOSED状态后,连接就完全释放了,这是TCP连接释放的第四次挥手。

同时关闭连接

正常情况下,通信一方请求连接关闭,另一方响应连接关闭请求,并且被动关闭连接。但是若出现同时关闭连接请求时,通信双方均从ESTABLISHED状态转换为FIN_WAIT_1状态。任意一方收到对方发来的FIN报文段后,其状态均有FIN_WAIT_1转变成CLOSING状态,并发送最后的ACK数据段。当收到最后的ACK数据段。当收到最后的ACK数据段后,状态变成TIME_WAIT,在等待2MSL时间后进入到CLOSED状态,最终释放整个TCP连接。
在这里插入图片描述

TCP的状态机

TCP所谓的“连接”,只是通信双方维护一个“连接状态”,让它看上去好像有连接一样,其实TCP连接是虚拟的连接不上电路连接。
在这里插入图片描述
下面这幅图是简洁版:
在这里插入图片描述

状态说明

  • CLOSED:表示初始状态,对服务端和客户端都一样。
  • LISTEN:表示监听状态。服务端调用了listen函数使其处于监听状态,此时可以accept(接收)客户端连接。
  • SYN_SENT:表示客户端已经发送了SYN报文端,则会处于该状态。当客户端调用connect函数发起连接请求时,首先发SYN给服务端,然后自己进入SYN_SENT状态,并等待服务端发送SYN+ACK作为请求应答。
  • SYN_RCVD:表示服务端收到客户端发送SYN报文段。服务端收到这个报文段后,进入SYN_RCVD状态,然后发送ACK+SYN给客户端。
  • ESTABLISHED:表示TCP连接已经成功建立,通信双方可以开始传输数据。服务端发送完ACK+SYN并收到来自客户端的ACK后进入该状态,客户端收到来自服务端的SYN+ACK并发送ACK后也进入该状态。
  • FIN_WAIT_1:表示主动关闭连接。无论哪方调用close函数发送FIN报文都会进入这个状态。
  • FIN_WAIT_2:表示被动关闭方同意关闭连接。主动关闭连接芳收到被动关闭方返回的ACK后,会进入该状态。
  • TIME_WAIT:表示收到对方的FIN报文并发送了ACK报文,就等2MSL后即可回到CLOSED状态。如果FIN_WAIT_1状态下,收到对方同时带FIN标志和ACK标志的报文时,可以直接进入TIME_WAIT状态,而无需进入FIN_WAIT_2状态。
  • CLOSING:表示双方同时关闭连接。如果双方几乎同时调用close函数,那么会出现双方同时发送FIN报文的情况,就好出现CLOSING状态,表示双方都在关闭连接。
  • CLOSE_WAIT:表示被动关闭方等待关闭。当收到对方调用close函数发送的FIN报文时,回应对方ACK报文,此时进入CLOSE_WAIT状态。
  • LAST_ACK:表示被动关闭方发送FIN报文后,等待对方的ACK报文状态,当收到ACK后进入CLOSED状态。

TCP相关术语解析

连接建立的超时

在这里插入图片描述

  • 在这个输出中有趣的一点是客户间隔多长时间发送一个SYN,试图建立连接。第2个SYN与第1个的间隔是5.8s,而第3个与第2个的间隔是24s。
  • 作为一个附注,这个例子是运行38分中后客户机启动tcp连接。这对应初始版本号为291008001(38606400 * 2)。另外,因为这是系统启动后的第一个TCP连接,因此客户的端口号是1024(0-1023是知名端口号)。
    在这里插入图片描述
  • tcp报文超时重传机制,第一次6s,第二次24秒。

最大报文段长度

  • 在有些书中,将它看作可协商 选项。它并不是任何条件下都可协商。当建立一个连接时,每一方都有用于通告它期望接收的MSS选项(MSS选项只能出现在SYN报文段中)。如果一方不接收来自另一方的MSS值,则MSS就定为默认值536字节。
  • 一般来说,如果没有分段发送,MSS还是越大越好(这也并不总是正确)。报文段越大允许每个报文段传送的数据就越多,相对IP和TCP首部有更高的网络利用率。当TCP发送一个SYN时,或者是因为一个本地应用进程想发起一个连接,或者是因为另一端的主机收到了一个连接请求,它能将MSS值设置为外出接口上的MTU长度减去固定的IP首部和TCP首部长度。对于一个以太网,MSS值可达1460字节。使用IEEE 802.3封装,它的MSS可达1452字节。
  • 如果目的IP地址为“非本地的(nonlocal)”,MSS通常的默认值是536。而区分地址是本地还是非本地是简单的,如果目的IP地址的网络号与子网号都和我们的相同,则是本地的;如果目的IP地址的网络号与我们的完全不同,则是非本地的;如果目的IP地址的网络号与我们的相同而子网号与我们的不同,则可能是本地的,也可能是非本地的。大多数TCP实现版都提供了一个配置选项,让系统管理员说明不同的子网是属于本地还是非本地。这个选项的设置将确定MSS可以选择尽可能的大(达到外出接口的MTU)或是默认值536。
    在这里插入图片描述

TCP的半关闭

在这里插入图片描述

  • TCP提供了连接的一端在结束它的发送后还能接收来自另一端数据的能力。这就是所谓的半关闭。正如我们早些时候提到的只有很少的应用程序使用它。
  • 为什么要有半关闭?一个例子是Unix中的rsh命令,它将完成在另一个系统上执行一个命令。命令:% rsh bsdi sort < datafile
  • 将在主机bsdi上执行sort排序命令,rsh命令的标准输入来自文件datafile。rsh将在它与在另一个主机上执行的程序间建立一个TCP连接。rsh的操作很简单:它将标准输入(datafile)复制给TCP连接,并将结果从TCP连接中复制给标准输出(我们的终端)。
  • 没有半关闭,需要其他的一些技术让客户通知服务器客户端已经完成了它的数据传送,但仍然要接收来自服务器的数据。使用两个TCP连接也可作为一个选择。
    在这里插入图片描述

TCP相关疑问

为什么是四次挥手

因为当处于LISTEN状态的服务器端收到来自客户端端的SYN报文(客户端希望新建一个TCP连接)时,它可以把ACK(确认应答)和SYN(同步位标志)放在同一个报文里来发送给客户端。但在关闭TCP连接时,当收到对方的FIN报文时,对方仅仅表示对方已经没有数据发送给你了,但是你自己可能还要数据需要发送给对方,则等你发送完剩余的数据给对方之后,在发送FIN报文给对方来表示你的数据已经发送完毕了,并请求关闭连接,所以通常情况下,这里的ACK报文和FIN报文都是分开发送的。

为什么一定要三次握手

  1. 连接是双向的,只有三次才能保证双方都是收发正常的。
  2. 减少资源浪费。
    产生浪费的原因是tcp的超时重传机制和连接建立后等到connectTimeout(tcp默认连接建立后2个小时候没有数据请求到达才关闭连接)之后才会关闭连接。
    具体过程如下:
    • 当客户端向服务器发送一个连接请求时,由于某种原因长时间驻留在网络节点中,无法到达服务器,由于TCP的超时重传机制,当客户端在特定的时间内没有收到服务端的确认应答信息,则会重新向服务端发送连接请求,且该请求得到服务器的响应并正常建立连接,进入传输数据,当数据传输完毕,并是否TCP连接。
    • 若此时第一次发送的连接请求报文延迟了一段时间后,到达了服务端,本来这是一个早已经失效的报文段,但是服务端收到该连接请求后误以为客户端又发出了一次新的连接请求,于是服务端向客户端发出确认应答报文段,并同意建立连接。
    • 如果没有采用三次握手,由于服务端发送了确认应答信息,则表示新的连接已经成功建立,但是客户端此时并没有向服务端发出任何连接请求,因此客户端忽略服务端的确认应答报文,更不会向服务端传输数据。而服务端却认为新的连接已经建立了,并在一直等待客户端发送数据,这样服务端一直处于等待结束数据的状态,直到超出计数器的设定值,则认为客户端出现异常,并且关闭这个连接。在这个 过程中浪费服务器的资源。
    • 如果采用三次握手,客户端就不会向服务器发出确认应答消息,服务端由于没有收到客户端的确认应答信息,从而判定客户端并没有请求建立连接,从而不建立该连接。

为什么TIME_WAIT状态必须等待2MSL时间,而不直接进入CLOSED状态

  1. TIME_WAIT确保有足够的时间让对端收到ACK,如果被动关闭的哪方没有收到ACK,就好超时重发FIN。因为最后一次确认应答ACK报文段很有可能丢失,因为使被动关闭处在LAST_ACK状态,此时被动关闭方会重复发送FIN报文段,主动关闭方在2MSL时间内收到FIN报文,重新发送ACK应答信息,并重新启动2MSL计时器,直到通信双方都进入CLOSED状态。如果主动关闭方没有等待2MSL时间,被动关闭方在没有收到ACK报文段后,重发FIN报文,但是无法收到主动关闭方的ACK报文,导致被动关闭方就无法正常进入CLOSED状态,一直无法释放TCP连接。
  2. 有足够的时间让这个连接不会跟后的连接混在一起,导致数据混乱。防止已失效的请求连接出现在本连接中。在连接2MSL等待时,任何迟到的报文段将被丢弃;因为处于2MSL等待时,由该插口(插口就是IP+PORT对的意思,socket)定义的连接在这段时间内将不能在被使用,这样就可以使下一个新的连接中不会出现这种旧的连接上以前延迟的保文段;也就是报文段的存活时间是2MSL,超过这个时间报文不再可用。

参考

图解TCP连接建立与释放

  • 1
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

融极

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值