TCP的三次握手与四次挥手

TCP的三次握手与四次挥手

TCP(Transmission Control Protocol,传输控制协议)是一种面向连接的、可靠的、基于字节流的通信协议,数据在传输前要建立连接,传输完毕后还要断开连接。

客户端在收发数据前要使用 connect() 函数和服务器建立连接。建立连接的目的是保证IP地址、端口、物理链路等正确无误,为数据的传输开辟通道。

TCP数据报结构

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DXmW4nlp-1581085715249)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1581077086032.png)]

几个重要的字段:

  1. 序号:Seq( Sequence Number ) 序号占32位,用来标识从计算机A发送到计算机B的数据包的序号,计算机发送数据时对此进行标记。
  2. 确认号:Ack( Acknowledge Number ) 确认号占32位,客户端和服务器端都可以发送,Ack = Seq + 1。
  3. 标志位:每个标志位占用1Bit,共有6个, 分别为 URG、ACK、PSH、RST、SYN、FIN,具体含义如下:
    • URG:紧急指针(urgent pointer)有效。
    • ACK:确认序号有效。
    • PSH:接收方应该尽快将这个报文交给应用层。
    • RST:重置连接。
    • SYN:建立一个新连接。
    • FIN:断开一个连接。

对英文字母缩写的总结:Seq 是 Sequence 的缩写,表示序列;Ack(ACK) 是 Acknowledge 的缩写,表示确认;SYN 是 Synchronous 的缩写,愿意是“同步的”,这里表示建立同步连接;FIN 是 Finish 的缩写,表示完成。

TCP三次握手,建立连接

TCP建立连接时要传输三个数据包,俗称三次握手(Three-way Handshaking)

  • [Shake 1] 套接字A:“你好,套接字B,我这里有数据要传送给你,建立连接吧。”
  • [Shake 2] 套接字B:“好的,我这边已准备就绪。”
  • [Shake 3] 套接字A:“谢谢你受理我的请求。”

使用 connect() 建立连接时,客户端和服务器端会相互发送三个数据包,请看下图:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sKEKR57C-1581085715250)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1581077527135.png)]

1)第一次握手:建立连接,客户机发出SYN包,随机生成一个x,使seq=x,并进入SYN-SENT状态,等待服务器确认

2)第二次握手:服务器收到SYN包,也创建一个SYN包,并2置SYN和ACK位为1,再随机生成一个y,使seq=y,将ack=x+1,发送给客户端,进入SYN-RECV状态

3)第三次握手:客户端收到数据包,检测SYN和ACK位,知道是服务器发送的确认包,同时创建一个ack=y+1的数据包发送给服务器,进入ESTABLISED状态,表示连接已经建立

4)服务器收到数据包,检查ack字段是否为y+1,也进入ESTABLISED状态

**重要说明:**三次握手的关键是要确认对方收到了自己的数据包,这个目标就是通过“确认号(Ack)”字段实现的。计算机会记录下自己发送的数据包序号 Seq,待收到对方的数据包后,检测“确认号(Ack)”字段,看Ack = Seq + 1是否成立,如果成立说明对方正确收到了自己的数据包。

TCP四次握手断开连接

建立连接需要三次握手,断开连接需要四次握手,可以形象的比喻为下面的对话:

  • [Shake 1] 套接字A:“任务处理完毕,我希望断开连接。”
  • [Shake 2] 套接字B:“哦,是吗?请稍等,我准备一下。”
  • 等待片刻后……
  • [Shake 3] 套接字B:“我准备好了,可以断开连接了。”
  • [Shake 4] 套接字A:“好的,谢谢合作。”

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PTK9XsEX-1581085715251)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1581078272993.png)]

1)客户端发出连接释放报文,即FIN数据包,进入FIN_WAIT_1状态(seq=u)

2)服务器收到数据包,检测FIN标志位后,先发送“确认包”,seq=v,ack=u+1,进入CLOSE_WAIT状态

注意:服务器收到请求后并不是立即断开连接,而是先向客户端发送“确认包”,告诉它我知道了,我需要准备一下才能断开连接。

3)客户端收到数据包后进入FIN_WAIT_2状态,等待服务器再次发送数据包

4) 等待片刻后,服务器准备完毕,可以断开连接,于是再主动向客户端发送 FIN 包, seq=w,ack=u+1,然后进入LAST_ACK状态

5)客户端收到FIN包后,再次发送ACK包,ack=w+1,seq=u+1,然后进入TIME_WAIT状态

TIME_WAIT状态需要等待2MSL才会进入CLOSE状态,目的:为了保证服务器收到ACK包,如果服务器未收到,会重传上一个FIN包(在2MSL内)

6)服务器收到ACK包,就断开连接,进入CLOSE状态

常见的面试问题

【问题1】为什么连接的时候是3次握手,关闭的时候是4次握手?

答:因为当Server端收到Client端的SYN连接请求时,可以直接发送SYN和ACK报文,其中ACK用来应答,SYN用来同步。但在关闭连接时,当Server端收到FIN,可能并不会立即关闭SOCKET,所以只能回复一个ACK报文表示收到了SYN包,等待Server端的所有数据发送完了,才会发送FIN报文,因此需要四次握手。

【问题2】为什么TIME_WAIT状态需要经过2MSL(最大报文段生存时间)才能返回到CLOSE状态?

答:**MSL就是报文最大生存时间, 2MSL就是一个发送和一个回复所需的最大时间。 ** TCP 是面向连接的传输方式 , 必须保证数据能够正确到达目标机器,不能丢失或出错 ,而网络是不可靠的,有可能最后一个ACK丢失了,TIME_WAIT状态就是用来重发丢失的报文的。在Client发送出最后ACK确认包后,如果Server未收到,就会不断地重复发送FIIN数据包。Client会设置一个计时器,等待2MSL的时间,在该时间段内再次收到FIN包,那么Client会重发ACK并再次等待2MSL。 如果直到2MSL,Client都没有再次收到FIN,那么Client推断ACK已经被成功接收,则结束TCP连接。

【问题3】 为什么不能用两次握手进行连接?

答:三次握手需要完成2个重要的功能,既要双方做好发送数据的准备工作(双发都知道彼此已准备好了),也要允许双方就初始序列号进行协商,这个seq需要在握手过程中发送和确认。

如果改成2次握手连接可能会发生死锁。当C给S发送一个SYN包,S收到并发送确认应答包。如果只有2次,此时S认为连接已经建立就开始发送数据,但这个确认应答包如果在传输过程中丢失了,C没有收到便无法知道S是否已经准备好,不知道S建立怎样的序列号甚至怀疑S释放收到自己的连接请求。在这种情况下,C认为连接未成功,将忽略S发来的任何数据包,只等待确认应答包,而S在发出数据包超时后,重复发出同样的分组,这就形成了死锁。

【问题4】如果已经建立了连接,但是Client突然出现故障了怎么办?

TCP还设有保活计时器,如果客户端出现故障,服务器不能一直等下去,白白浪费资源。服务器每收到一次客户端的请求后都会重新复位这个计时器,时间通常是设置为2个小时,若两个小时还没有收到客户端的任何数据,服务器就会发送一个探测报文段,以后每隔75秒钟发送一次。若一连发送10个探测报文仍然没有反应,服务器就认为客户端出了故障,接着就关闭连接。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值