笔记-TCP的三次握手四次挥手

TCP三次握手例子

假设你的电脑(客户端A)尝试通过TCP连接到一个网站的服务器(服务器B)。服务器的IP地址是192.168.1.1,客户端的IP地址是192.168.1.2,而你想要访问的服务(比如一个网页)是通过标准的HTTP服务端口80提供的。

  1. SYN步骤:
    • 客户端A(192.168.1.2:12345)生成一个随机的初始序列号,比如1000,并向服务器B的80端口发送一个TCP段,其SYN位设置为1。
    • 此时的TCP包头部信息大致如下:makefileCopy code源地址:192.168.1.2:12345 目的地址:192.168.1.1:80 Seq=1000 ACK=0 Flags=[SYN]
    • 服务器B接收到这个请求。
  2. SYN-ACK步骤:
    • 服务器B(192.168.1.1:80)收到请求后,会从它自己的端口回应客户端A。它也会生成一个随机的初始序列号,比如5000,并且把确认号设置为客户端A的序列号加1(也就是1001)。
    • 服务器B发送的TCP包头部信息大致如下:makefileCopy code源地址:192.168.1.1:80 目的地址:192.168.1.2:12345 Seq=5000 ACK=1001 Flags=[SYN, ACK]
    • 客户端A接收到这个响应。
  3. ACK步骤:
    • 客户端A(192.168.1.2:12345)再次发送一个TCP段给服务器B,ACK位设置为1,序列号为1001(表示客户端A准备好接收服务器B的下一个字节),确认号为5001(表示服务器B发送的数据已被确认,服务器可以发送下一个字节了)。
    • 此时客户端A发送的TCP包头部信息大致如下:makefileCopy code源地址:192.168.1.2:12345 目的地址:192.168.1.1:80 Seq=1001 ACK=5001 Flags=[ACK]
    • 服务器B接收到这个确认。

TCP三次握手作用包括:

  1. 同步序列号:由于TCP是基于字节流的,各个数据包的顺序非常重要。三次握手可以同步连接双方的初始序列号,从而保证数据传输的顺序和完整性。
  2. 确认双方的接收和发送能力:三次握手确保了双方都能够接收和发送数据。首次握手确认了服务器的接收能力,第二次握手确认了服务器的发送能力以及客户端的接收能力,最后一次握手则确认了客户端的发送能力。
  3. 防止旧的连接请求造成混乱:网络中可能存在旧的连接请求数据包(因为延迟或重发),这些过时的数据包如果被接收,可能会造成错误的连接建立。三次握手通过确认和序列号机制,使得旧的连接请求不会被错误地接受。
  4. 资源分配:在三次握手过程中,TCP堆栈会分配缓冲区和变量以跟踪连接状态。通过这样的过程,只有在双方都确认连接请求之后,才会完成资源分配,避免了因为未完成连接而造成的资源浪费。

三次握手是对建立TCP连接过程的最小化要求,它可以有效地启动一个双向通信会话,同时避免了一些常见的网络通信问题。如果减少到两次握手,那么就无法解决上述的第三个问题,也就是说,如果网络中存在延迟的连接请求,那么这样的请求可能会导致不必要的连接建立,从而造成混乱。三次握手是在效率和可靠性之间的一个妥协。

四次挥手断开TCP连接的例子:

假设客户端A与服务器B之间建立了一个TCP连接,并且在此期间它们已经交换了一些数据。现在,客户端A决定关闭这个连接。以下是关闭过程的详细步骤和假设的序列号及确认号。

  1. 第一次挥手
    • 客户端A发送一个FIN标志的段给服务器B,指示A已经完成了数据的发送。
    • 假设客户端A之前发送的最后一个数据段的序列号是10000。
    • 客户端A的FIN段的序列号将会是10001(因为TCP协议规定FIN标志的段也消耗一个序列号)。
    • 如果服务器B之前发送给客户端A的最后一个数据段的序列号是5000,那么客户端A发送的ACK确认号将是5001,确认它已经收到了直到序列号5000的所有数据。
    • 段信息如下:cssCopy code源地址:客户端A 目的地址:服务器B Seq=10001 Ack=5001 Flags=[FIN, ACK]
  2. 第二次挥手
    • 服务器B收到客户端A的FIN段,发送一个ACK段回应,确认收到A的结束请求。
    • 服务器B的ACK段的确认号将是客户端A的序列号加1,也就是10002,因为它需要确认收到了包含FIN标志的那个序列号。
    • 此时,服务器B还没有准备好关闭连接或者可能仍有数据需要发送给客户端A。
    • 段信息如下:cssCopy code源地址:服务器B 目的地址:客户端A Seq=服务器B当前的序列号 Ack=10002 Flags=[ACK]
  3. 第三次挥手
    • 服务器B已完成数据的发送,并且准备关闭连接,发送一个FIN标志的段给客户端A。
    • 假设服务器B之前发送的最后一个数据段的序列号是8000。
    • 服务器B发送的FIN段的序列号将会是8001。
    • 服务器B在发送FIN之前也已经收到了客户端A之前的所有数据,所以ACK确认号将是客户端A之前的确认号,也就是10002。
    • 段信息如下:cssCopy code源地址:服务器B 目的地址:客户端A Seq=8001 Ack=10002 Flags=[FIN, ACK]
  4. 第四次挥手
    • 客户端A收到服务器B的FIN段,发送一个ACK段回应,确认收到B的结束请求。
    • 客户端A的ACK段的确认号将是服务器B的序列号加1,也就是8002。
    • 此时客户端A会等待足够的时间确保服务器B收到了这个ACK段,这个时间通常是该连接的往返时延的两倍。
    • 殅信息如下:cssCopy code源地址:客户端A 目的地址:服务器B Seq=10002 Ack=8002 Flags=[ACK]

TCP的四次挥手(Four-way Handshake)断开连接的过程比建立连接的三次握手(Three-way Handshake)要复杂,这主要是因为TCP连接是全双工的,意味着每个方向的通信是独立的。这里是为什么需要四次挥手的一些原因:

  1. 全双工通信:在TCP连接中,数据传输是全双工的,即数据可以在两个方向上同时进行。因此,每个方向都必须单独关闭,这就需要两个FIN标志和两个ACK标志。
  2. 确保数据完全传输:TCP连接的一方(比如客户端)发送FIN标志仅表示它没有更多的数据要发送,但是它仍然可以接收数据。服务器在收到这个FIN之后,可能仍然有数据要发送给客户端。服务器必须确保所有传出的数据都被客户端接收到,然后才能安全地发送它自己的FIN标志来关闭连接的另一个方向。
  3. 防止数据丢失:四次挥手允许每一方确认它们已经接收到对方发送的最后一个包。这意味着如果任何FIN或ACK在传输过程中丢失,连接不会立即关闭,从而允许重传丢失的包,确保连接的可靠终止。
  4. TIME_WAIT状态:客户端发送最后一个ACK后,它还需要等待足够的时间(称为2MSL,Maximum Segment Lifetime)以确保服务器收到了这个ACK。如果服务器没有收到ACK,它将重新发送FIN包。TIME_WAIT状态确保了旧的连接残留的数据包不会在新的连接中出现,从而避免可能的混淆。

总结来说,四次挥手的过程确保了连接的双方都能够完全完成数据传输,并且优雅地关闭连接,没有任何一方突然中断连接导致数据丢失。这也是为什么不能简化为三次或更少次数的原因,因为TCP设计的优先考虑是确保数据传输的可靠性和完整性。

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注