TCP三报文握手和四报文挥手

三报文“握手”

在这里插入图片描述

TCP规定:SYN=1的报文段 不 能 携 带 数 据 \color{red}{不能携带数据} 。普通的TCP报文段可以携带数据,但如果不携带数据,则不消耗序号。

  1. 最初,客户端 和 服务器 都是处于 关 闭 状 态 \color{red}{关闭状态} 。TCP服务器进程首先 创 建 传 输 控 制 块 \color{red}{创建传输控制块} ,用来存储TCP链接中的一些重要信息,之后就准备接受TCP客户进程的连接请求。此时,TCP服务器进程就会进入 监 听 状 态 \color{red}{监听状态} ,等待客户的请求。TCP服务器进程是被动等待来自TCP客户进程的连接请求,而不是主动发起,因此称为 被 动 打 开 连 接 \color{red}{被动打开连接}
  2. TCP客户进程也是首先建立连接控制块,然后向TCP服务器发送 T C P 连 接 请 求 报 文 段 \color{red}{TCP连接请求报文段} TCP[SYN=1, seq=x],并进入同步已发送状态,称为 主 动 打 开 连 接 \color{red}{主动打开连接} SYN=1表明这是一个TCP链接请求报文段,序号字段seq=x,作为TCP客户进程所选择的初始序号。
  3. TCP服务器进程收到客户端发来的连接请求报文段后,如果同意建立连接,则向TCP客户进程发送 T C P 连 接 确 认 报 文 段 \color{red}{TCP连接确认报文段} TCP[SYN=1, ACK=1, seq=y, ack=x+1],并进入同步已接收状态。SYN=1, ACK=1表明这是一个TCP连接请求确认报文段,seq=y作为TCP服务器进程所选择的初始序号,ack=x+1这是对TCP客户进程所选择的初始序号的确认。
  4. TCP客户进程收到TCP连接请求确认报文段后,还要向TCP服务器进程发送一个 普 通 的 T C P 确 认 报 文 段 \color{red}{普通的TCP确认报文段} TCP[ACK=1, seq=x+1, ack=y+1],并 进 入 连 接 已 建 立 状 态 \color{red}{进入连接已建立状态} ACK=1表明这是一个普通的TCP确认报文段,序号字段seq=x+1是因为TCP客户进程发送的第一个TCP报文段的序号为x,并且不携带数据。确认段ack=y+1是对TCP服务器进程所选择的初始序号的确认。TCP服务器进程收到该确认报文段后也进入 连 接 已 建 立 状 态 \color{red}{连接已建立状态} .

几个问题?

可不可以只握手两次?即不发送最后一次的普通TCP确认报文段

不 可 以 \color{red}{不可以} 。假设TCP客户进程发出一个TCP连接请求报文段,但该报文段在某些网络结点长时间滞留了,这必然会造成对该报文段的超时重传。假设重传的报文段被TCP服务器进程正常接收,TCP服务器进程向TCP客户进程发送一个TCP连接请求确认报文段,并进入 连 接 已 建 立 状 态 \color{red}{连接已建立状态} 。由于这是已经改为两报文握手,因此TCP服务器进程发送完TCP连接请求确认报文段后,进入的是连接已建立状态,而不像三报文握手那样进入同步已接收状态。TCP客户进程收到连接请求确认报文段后也进入连接建立状态。现在TCP双方都处于连接已建立状态,它们可以相互传输数据,之后再通过四报文挥手来释放连接,TCP双方都进入关闭状态。 一 段 时 间 后 \color{red}{一段时间后} ,之前滞留在网络中失效的TCP连接请求报文段到达了TCP服务器进程,TCP服务器进程会误认为这是TCP客户进程又发起了一个新的TCP连接请求,于是给TCP客户进程发送TCP连接请求确认报文段,并进入连接已建立状态。该报文段到达TCP客户进程,由于TCP客户进程实际上没有发送新的TCP连接请求,并且处于关闭状态,因此不会理会该报文段。但是TCP服务器进程已经进入了连接已建立状态,他认为新的TCP链接已经建立好了,并一直等待TCP客户进程发来数据,这将白白浪费TCP服务器进程所在主机的很多资源!

如果采用的是三次握手,就算那一次失效的报文传送过来了,服务器收到了失效的报文并回复了确认报文,但是客户端不会再次发出确认。由于服务器收不到确认,就知道客户端并没有请求连接。

四报文“挥手”

在这里插入图片描述

TCP规定:终止位FIN=1的报文段即使不携带数据,也要消耗一个序号。

  1. TCP客户进程主动关闭TCP连接,TCP客户进程会发送TCP连接释放报文段[FIN=1, seq=u],并进入终止等待-1状态。seq=u u = 结 束 报 文 段 序 号 + 1 u = 结束报文段序号+1 u=+1FIN=1是终止报文段。
  2. 服务器接收到客户端发来的FIN包之后,会发送一条普通的TCP确认报文段[ACK=1, seq=v, ack=u+1],并进入关闭等待状态。ACK=1表明这是一个普通的TCP确认报文段,序号seq=v中的 v 等于TCP服务器进程之前已传送过的数据的最后一个字节的序号加1,确认段ack=u+1是对TCP连接释放报文段的确认。TCP服务器进程会告诉高层应用进程,TCP客户进程要断开与自己的TCP连接。此时,从TCP客户进程到TCP服务器进程这个方向的连接就释放了。这时TCP连接属于半关闭状态,即TCP客户进程没有数据要发送了,但TCP服务器进程如果有数据要发送,TCP客户进程仍要接收。从TCP服务器进程到TCP客户进程这个方向的连接并未关闭
  3. TCP客户进程收到TCP服务器进程的确认段后,进入终止等待-2状态。TCP服务器进程发送TCP连接释放报文段[FIN=1, ACK=1, seq=w, ack=u+1],并进入 最 后 确 认 状 态 \color{red}{最后确认状态} FIN=1, ACK=1表明这是TCP连接释放报文段,同时也对之前收到的报文段进行确认。seq=w是对之前TCP客户进程发送数据的字节序号。ack=u+1这是对之前收到的TCP连接释放报文段额重复确认。
  4. TCP客户进程收到上面报文段后,又对TCP服务器进程发送一个普通的TCP确认报文段[ACK=1, seq=u+1, ack=w+1],之后进入时间等待状态。ACK=1表明这是普通的TCP确认报文段,序号seq=u+1是因为TCP客户进程之前发送的TCP连接释放报文段虽然不携带数据,但要消耗一个序号。确认段ack=w+1这是对所收到的TCP连接释放报文段的确认。TCP服务器进程收到该报文段后就进入关闭状态,而TCP客户进程还要经过2MSL后才能进入关闭状态。MSL是最长报文段寿命,建议为2分钟。

几个问题?

为什么客户进程最后要等待2MSL时间?

防止客户进程最后发去的 ACK 没传送到服务器,如果服务器没收到客户端的 ACK,肯定会选择重发一次 FIN 包,那么此时如果客户端已经关闭了,客户端就不能再发 ACK 确认收到了。这会造成TCP服务器进程反复重传TCP连接释放字段,无法进入关闭状态。2MSL等待时长可以确保收到最后一个服务器发送的TCP确认报文段而进入关闭状态。另外TCP客户进程再经历2MSL时间就可以使本次连接所产生的所有报文段都从网络中消失。

为什么不能三次挥手呢?
  • 首先如果去掉最后一次挥手,那么服务器端就不知道自己要关闭的确认报文有没有传输成功,可能半路上就失败了,但是此时客户端不知道,导致客户端一直在等待服务器关闭,但是此时服务器端直接就关闭了;
如果已经建立了连接,但是客户端突然出现故障了怎么办?

TCP还设有一个保活计时器,显然,客户端如果出现故障,服务器不能一直等下去,白白浪费资源。

  • 服务器每收到一次客户端的请求后都会重新复位这个计时器,时间通常是设置为2小时。
  • 若两小时还没有收到客户端的任何数据,服务器就会发送一个探测报文段,以后每隔75秒发送一次。若一连发送10个探测报文仍然没反应,服务器就认为客户端出了故障,接着就关闭连接。

。若一连发送10个探测报文仍然没反应,服务器就认为客户端出了故障,接着就关闭连接。



综述:

在这里插入图片描述

  • CLOSED:表示初始状态。对服务端和C客户端双方都一样。
  • LISTEN:表示监听状态。服务端调用了listen函数,可以开始accept连接了。
  • SYN_SENT:表示客户端已经发送了SYN报文。当客户端调用connect函数发起连接时,首先发SYN给服务端,然后自己进入SYN_SENT状态,并等待服务端发送ACK+SYN。
  • SYN_RCVD:表示服务端收到客户端发送SYN报文。服务端收到这个报文后,进入SYN_RCVD状态,然后发送ACK+SYN给客户端。
  • ESTABLISHED:表示连接已经建立成功了。服务端发送完ACK+SYN后进入该状态,客户端收到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状态。

写的好的文章:https://blog.csdn.net/qzcsu/article/details/72861891

  • 2
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值