TCP三次握手四次挥手

TCP的运输连接管理:

TCP是面向连接的协议。运输连接时用来传送TCP报文的。TCP运输连接的建立和释放是每次面向连接的通信中必不可少的过程。因此,运运输连接就有三个阶段:连接建立、数据传送和连接释放。运输连接的管理就是使运输连接的建立和释放都能正常地进行。

在TCP连接建立过程中要解决以下三个问题:

1、要使每一方能够确知对方的存在

2、要允许双方协商一些参数(如最大窗口值、是否使用窗口扩大选项和时间戳选项以及服务质量等)。

3、能够对运输实体资源进行分配

TCP连接的建立采用客户服务器方式。主动发起连接建立的应用进程叫客户而被动等待连接建立的应用进程叫做服务器。

在上图中A主动打开连接,而B被动打开连接。

       A向B发出连接请求报文段,这时首部中的同步位SYN=1,同时选择一个初始序列号seq=想,TCP规定,SYN报文段(即SYN=1的报文段),不能携带数据,但是要消耗掉一个序号。

       B收到连接请求报文段后,如同意建立连接,则向A发送确认,在确认报文段中应把SYN位和ACK位都置1,确认号ack=x+1,同时也为自己选择一个初始序号seq=y,请注意,这个报文段也不能携带数据,但同样要消耗掉一个序号。

       TCP客户收到B的确认后,还要向B给出确认,确认报文段的ACK置1,确认号ack=y+1,而自己的序号seq=x+1.TCP的标准规定ACK报文段可以携带数据,但如果不携带数据则不消耗序号。

       上面给出的连接建立过程叫做三次握手,B给A发送的报文段,也可拆成两个报文段,可以先发送一个确认报文段(ACK=1 ack=x+1)然后再发送一个同步报文,这样的过程就变成了四次握手,但效果是一样的。

为什么A最后还要发送一次确认呢?

       三次握手的目的:相信前两次握手很好理解,一次是客户端向服务器端发出连接请求,此时只能是客户端向服务端发送数据,而服务端不能向客户端发送数据。第二次是服务端向客户端发送的连接请求,这次过后双方都可以发送数据了,那其实两次连接就能解决的问题为什么还要第三次呢?第三次的的握手是为了防止已经失效的连接请求报文突然又传到了服务端,从而产生错误。

       数据传输结束后,通信的双方都可释放连接,A的应用进程先向其TCP发出连接释放报文段,并停止再发送数据,主动关闭TCP连接,A把连接释放报文段首部的终止控制位FIN置1,其序号seq=u,它等于把前面传送过的数据最后一个字节的序号加1

       B收到连接释放报文后即发出确认,确认号是ack=u+1,而这个报文段自己的序号是v,等于B前面传送过的数据最后一个字节的序号加1,然后B就进入关闭等待状态。TCP服务器进程这时应通知高层应用进程,因为从A到B这个方向的连接就释放了,这时的TCP连接处于半关闭状态,即A已经没有数据要发送了,但若B发送数据A仍要接收,也就是说,从B到A这个方向的连接并未关闭,这个状态可能会持续一段时间。A收到来自B的确认后,就进入终止等待状态,等待B发出的连接释放请求。

       若B已经没有要向A发送的数据,其应用进程就通知TCP释放连接,这时B发出的连接释放报文段必须使FIN=1,现假定B的序号为w,B还必须重复上次已经发送过的确认号ack=u+1,这时B就进入最后确认状态,等待A的确认,A在收到B的连接释放报文段后,必须对此发出确认,在确认报文段中把ACK置1,确认号ack=w+1,而自己的序号是seq=u+1,。然后进入到TIME_WAIT(时间等待状态)。请注意现在TCP连接还没有释放掉,必须经过时间等待计时器设置的时间后,A才进入到CLOSED转态。时间MSL叫最长报文段寿命。从A进入到TIME_WAIT状态后,要经过等待时间后才能进入CLOSED状态,才能开始建立下一个新的连接,当A撤销相应的传输控制块TCB后,就结束了这次TCP连接

为什么A在TIME_WAIT状态必须等待2MSL的时间呢?

1、为了保证A发送的最后一个ACK报文段能够到达B,如果A在TIME_WAIT状态不等待一段时间,而是在发送完ACK报文段后立即释放连接,那么久无法收到B重传的FIN+ACK报文段,因而也不会再发送一次确认报文段,这样B就无法按照正常步骤进入CLOSED状态。

2、防止已是小的连接请求报文出现在本连接中,A在发送完最后一个ACK报文段后,再经过时间2MSL,就可以使本连接持续的时间内产生的所有报文段都从网络中消失,这样就可以使下一个新的连接中不会出现这种旧的连接请求报文段。

为什么是三次握手四次挥手?

       TCP提供了一种可靠,面向连接,字节流,传输层的服务,采用三次握手建立一个连接,采用四次挥手来关闭一个连接。

       一个TCP连接通由一个4元组成,分别是两个IP地址和两个端口号,一个TCP连接通常分为3个阶段:启动,数据传输,退出(关闭)。当TCP接收到另一端的数据时,它会发送一个确认,但这个确认不会立即发送,一般会延迟一会,ACK是累积的,一个确认字节号N的ACK表示所有直到N的字节(不包括N)已经成功被接受了,这样的好处是如果一个ACK丢失,很可能后序的ACK就是已确认前的报文段了。

       一个完整的TCP连接是双向和对称的,数据可以在两个方向上平等地流动,给上层应用程序提供一种双工服务,一旦建立了一个连接,这个连接的一个方向上每个TCP报文段都包含了相反方向上的报文段的一个ACK。

       序列号的作用是使得一个TCP接收端可丢弃重复的报文段,记录以杂乱次序到达的报文段。因为TCP使用IP来传输报文段,而IP不提供重复消除或者保证次序正确的功能,另一方面TCP是一个字节流协议,绝不会以杂乱的次序给上层程序。因此TCP接收端会被迫先保持大序列号的数据不交给应用程序,直到缺失的小序列号的报文段被填满。

### TCP 三次握手四次挥手的过程及原理 #### 一、TCP 三次握手过程及原理 TCP 是一种面向连接的可靠传输协议,在数据传输前需要通过三次握手来建立连接。以下是其具体过程: 1. **第一次握手** 客户端向服务器发起连接请求,发送一个带有 SYN 标志位的数据包,并随机生成一个初始序列号 `Seq=x`,此时客户端进入 `SYN_SENT` 状态[^5]。 2. **第二次握手** 服务器收到客户端的 SYN 请求后,返回一个确认消息,该消息同时携带两个标志位:SYN 和 ACK。其中,SYN 表示同意建立连接并随机生成自己的初始序列号 `Seq=y`;ACK 则是对客户端序列号的确认,即 `Ack=x+1`。此时服务器进入 `SYN_RCVD` 状态[^4]。 3. **第三次握手** 客户端收到服务器的响应后,再次发送一个确认消息给服务器,此消息仅带有一个 ACK 标志位,用于确认服务器的序列号,即 `Ack=y+1`。随后,客户端进入 `ESTABLISHED` 状态,而服务器在接收到这个 ACK 后也进入 `ESTABLISHED` 状态,至此完成三次握手[^1]。 通过以上三个步骤,双方不仅建立了连接,还同步了各自的序列号和确认号,从而确保后续通信的可靠性[^3]。 --- #### 二、TCP 四次挥手过程及原理 由于 TCP 协议采用全双工模式工作,因此关闭连接时需分别处理双向通道的释放问题,这通常涉及四个阶段的操作,称为“四次挥手”。 1. **第一次挥手** 主动关闭的一方(通常是客户端)发送 FIN 报文通知对方自己已经没有数据要发送了,同时终止本方向上的数据流。此时,主动关闭方进入 `FIN_WAIT_1` 状态[^2]。 2. **第二次挥手** 被动关闭一方(通常是服务器)收到 FIN 报文后,回应一个 ACK 报文作为确认,设置 `Ack=seq+1`,并将被动关闭方的状态改为 `CLOSE_WAIT`。与此同时,主动关闭方则转变为 `FIN_WAIT_2` 状态[^4]。 3. **第三次挥手** 当被关闭方也没有更多数据待发时,它会再发送一个 FIN 报文告知主动关闭方准备完全断开连接。此时,被动关闭方变为 `LAST_ACK` 状态[^5]。 4. **第四次挥手** 主动关闭方接收到来自被动关闭方的 FIN 报文之后,回复最后一个 ACK 报文予以确认,然后进入 `TIME_WAIT` 状态。经过一段时间延迟(一般为两倍最大分组生存时间 MSL),如果未检测到异常情况,则正式关闭连接并转入 `CLOSED` 状态。同样地,被动关闭方在接受到最终 ACK 报文后立即切换至 `CLOSED` 状态,结束整个流程[^3]。 值得注意的是,“四次挥手”的核心在于允许两端独立管理各自方向上的资源回收,保障任何尚未送达的信息能够得到妥善处理[^2]。 --- ```python # Python模拟TCP三次握手四次挥手逻辑示意 class TCPSession: def __init__(self, client_seq, server_seq): self.client_seq = client_seq self.server_seq = server_seq def three_way_handshake(self): print(f"Client -> Server: SYN Seq={self.client_seq}") self.client_seq += 1 print(f"Server <- Client: SYN+ACK Ack={self.client_seq} Seq={self.server_seq}") self.server_seq += 1 print(f"Client -> Server: ACK Ack={self.server_seq}") def four_way_wavehand(self): print(f"Client -> Server: FIN Seq={self.client_seq}") print(f"Server <- Client: ACK Ack={self.client_seq + 1}") print(f"Server -> Client: FIN Seq={self.server_seq}") print(f"Client <- Server: ACK Ack={self.server_seq + 1}") session = TCPSession(0, 0) print("\n--- Three-Way Handshake ---") session.three_way_handshake() print("\n--- Four-Way Wavehand ---") session.four_way_wavehand() ``` ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值