zoukankan      html  css  js  c++  java
  • TCP的三次握手与四次挥手

    一、TCP报文格式

     

    TCP报文格式上图中有几个字段需要重点介绍下:
    (1)序号:Seq序号,占32位,用来标识从TCP源端向目的端发送的字节流,发起方发送数据时对此进行标记。
    (2)确认序号:Ack序号,占32位,只有ACK标志位为1时,确认序号字段才有效,Ack=Seq+1。
    (3)标志位:共6个,即URG、ACK、PSH、RST、SYN、FIN等,具体含义如下:
    (A)URG:紧急指针(urgent pointer)有效。
    (B)ACK:确认序号有效。
    (C)PSH:接收方应该尽快将这个报文交给应用层。
    (D)RST:重置连接。
    (E)SYN:发起一个新连接。
    (F)FIN:释放一个连接。

    需要注意的是:
    (A)标志位中的ACK、与确认序号Ack是不同的;
    (B)确认序号Ack=发起方Seq+1 两端配对;

    三次握手(three times handshake)即建立TCP连接,就是指建立一个TCP连接时,需要客户端和服务端总共发送3个包用来客户端与服务端TCP连接的建立;

    二、三次握手过程

    (1)第一次握手:Client将标志位SYN置为1,随机产生一个值seq=X,并将该数据包发送给Server,Client进入SYN_SENT状态,等待Server确认。
    (2)第二次握手:Server收到数据包后由标志位SYN=1知道Client请求建立连接,Server将标志位SYN和ACK都置为1,ack numbern=X+1,随机产生一个值seq=K,并将该数据包发送给Client以确认连接请求,Server进入SYN_RCVD状态。
    (3)第三次握手:Client收到确认后,检查ack number是否为X+1,ACK是否为1,如果正确则将标志位ACK置为1,ack=K+1,并将该数据包发送给Server,Server检查ack是否为K+1,ACK是否为1,如果正确则连接建立成功,Client和Server进入ESTABLISHED状态,完成三次握手,随后Client与Server之间可以开始传输数据了。

    如图主要是根据 ACK 与Ack number;

    三、TCP四次挥手

    由于TCP连接时全双工的,因此,每个方向都必须要单独进行关闭,这一原则是当一方完成数据发送任务后,发送一个FIN来终止这一方向的连接,收到一个FIN只是意味着这一方向上没有数据流动了,即不会再收到数据了,但是在这个TCP连接上仍然能够发送数据,直到这一方向也发送了FIN。首先进行关闭的一方将执行主动关闭,而另一方则执行被动关闭;

    (1)第一次挥手:Client发送一个FIN,用来关闭Client到Server的数据传送,Client进入FIN_WAIT_1状态,将标志位FIN和ACK置为1,序号为X,确认序号为Z=1;

    (2)第二次挥手:Server收到FIN后,发回一个ACK给Client,ACK(标志位ACK=1),确认序号为收到的序号加1,ack=X+1;

    (3)第三次挥手:Server发送一个FIN,用来关闭Server到Client的数据传送,Server进入LAST_ACK状态,将标志位FIN和ACK置为1,序号为Y,,确认序号为收到的序号加1,ack=X+1;

    (4)第四次挥手:Client收到FIN后,Client进入TIME_WAIT状态,发回ACK确认(标志位ACK=1),确认序号为收到的序号加1 ack=Y+1;

    为什么连接的时候是三次握手,关闭的时候却是四次握手?

    为什么需要三次握手


      在谢希仁著《计算机网络》第四版中讲“三次握手”的目的是“为了防止已失效的连接请求报文段突然又传送到了服务端,因而产生错误”。在另一部经典的《计算机网络》一书中讲“三次握手”的目的是为了解决“网络中存在延迟的重复分组”的问题。这两种不用的表述其实阐明的是同一个问题。
         谢希仁版《计算机网络》中的例子是这样的,“已失效的连接请求报文段”的产生在这样一种情况下:client发出的第一个连接请求报文段并没有丢失,而是在某个网络结点长时间的滞留了,以致延误到连接释放以后的某个时间才到达server。本来这是一个早已失效的报文段。但server收到此失效的连接请求报文段后,就误认为是client再次发出的一个新的连接请求。于是就向client发出确认报文段,同意建立连接。假设不采用“三次握手”,那么只要server发出确认,新的连接就建立了。由于现在client并没有发出建立连接的请求,因此不会理睬server的确认,也不会向server发送数据。但server却以为新的运输连接已经建立,并一直等待client发来数据。这样,server的很多资源就白白浪费掉了。采用“三次握手”的办法可以防止上述现象发生。例如刚才那种情况,client不会向server的确认发出确认。server由于收不到确认,就知道client并没有要求建立连接。”。主要目的防止server端一直等待,浪费资源。

    为什么需要四次挥手

      因是因为tcp是全双工模式,接收到FIN时意味将没有数据再发来,但是还是可以继续发送数据。

  • 相关阅读:
    ActiveMQ 默认用户名和密码
    # ActiveMQ连接超时问题(java.net.SocketException: Connection reset)
    SpringBoot(十) Logback 配置详解
    postgresql10以上的自动分区分表功能
    基于Redis实现延时队列服务
    Redis(十三):Redis分布式锁的正确实现方式
    Redis(十七):批量操作Pipeline
    Redis(十八):Redis和队列
    PostgreSQL SELECT INTO和INSERT INTO SELECT 两种表复制语句
    PostgreSQL 从文件时间戳获悉一些信息(如数据库创建时间)
  • 原文地址:https://www.cnblogs.com/leonardchen/p/6628103.html
Copyright © 2011-2022 走看看