精华内容
下载资源
问答
  • 该文档详细描述了wireshark抓包分析tcp三次握手四次挥手详解及网络命令,亲自整理,适合新手借鉴
  • 文章目录一.TCP简介二.TCP数据报结构三.TCP的三次握手四.TCP的四次挥手 一.TCP简介 TCP(Transmission Control Protocol,传输控制协议)是一种面向连接的、可靠的、基于字节流的通信协议,数据在传输前要建立连接,...
  • TCP 三次握手四次挥手,面试题详解,图文并茂,欢迎技术交流
  • TCP三次握手四次挥手详解 相对于SOCKET开发者,TCP创建过程和链接折除过程是由TCP/IP协议栈自动创建的.因此开发者并不需要控制这个过程.但是对于理解TCP底层运作机制,相当有帮助. 而且对于有网络协议工程师之类笔试...

    转载

    TCP三次握手四次挥手详解

    相对于SOCKET开发者,TCP创建过程和链接折除过程是由TCP/IP协议栈自动创建的.因此开发者并不需要控制这个过程.但是对于理解TCP底层运作机制,相当有帮助.

    而且对于有网络协议工程师之类笔试,几乎是必考的内容.企业对这个问题热情之高,出乎我的意料:-)。有时上午面试前强调这个问题,并重复讲一次,下午几乎每一个人都被问到这个问题。

    因此在这里详细解释一下这两个过程。

    TCP三次握手

    所谓三次握手(Three-way Handshake),是指建立一个TCP连接时,需要客户端和服务器总共发送3个包。

    三次握手的目的是连接服务器指定端口,建立TCP连接,并同步连接双方的序列号和确认号并交换 TCP 窗口大小信息.在socket编程中,客户端执行connect()时。将触发三次握手。

    第一次握手:
    客户端发送一个TCP的SYN标志位置1的包指明客户打算连接的服务器的端口,以及初始序号X,保存在包头的序列号(Sequence Number)字段里。

    第二次握手:
    服务器发回确认包(ACK)应答。即SYN标志位和ACK标志位均为1同时,将确认序号(Acknowledgement Number)设置为客户的I S N加1以.即X+1。

    第三次握手.
    客户端再次发送确认包(ACK) SYN标志位为0,ACK标志位为1.并且把服务器发来ACK的序号字段+1,放在确定字段中发送给对方.并且在数据段放写ISN的+1

    SYN攻击
    在三次握手过程中,服务器发送SYN-ACK之后,收到客户端的ACK之前的TCP连接称为半连接(half-open connect).此时服务器处于Syn_RECV状态.当收到ACK后,服务器转入ESTABLISHED状态.
    Syn攻击就是 攻击客户端 在短时间内伪造大量不存在的IP地址,向服务器不断地发送syn包,服务器回复确认包,并等待客户的确认,由于源地址是不存在的,服务器需要不断的重发直 至超时,这些伪造的SYN包将长时间占用未连接队列,正常的SYN请求被丢弃,目标系统运行缓慢,严重者引起网络堵塞甚至系统瘫痪。
    Syn攻击是一个典型的DDOS攻击。检测SYN攻击非常的方便,当你在服务器上看到大量的半连接状态时,特别是源IP地址是随机的,基本上可以断定这是一次SYN攻击.在Linux下可以如下命令检测是否被Syn攻击
    netstat -n -p TCP | grep SYN_RECV
    一般较新的TCP/IP协议栈都对这一过程进行修正来防范Syn攻击,修改tcp协议实现。主要方法有SynAttackProtect保护机制、SYN cookies技术、增加最大半连接和缩短超时时间等.
    但是不能完全防范syn攻击。
    TCP 四次挥手
    TCP的连接的拆除需要发送四个包,因此称为四次挥手(four-way handshake)。客户端或服务器均可主动发起挥手动作,在socket编程中,任何一方执行close()操作即可产生挥手操作。

    参见wireshark抓包,实测的抓包结果并没有严格按挥手时序。我估计是时间间隔太短造成。
    注意上面的字段标号地段和发送接收的内容序号,可能有个有错,记不住哪个了,后头要细看看

     

    第二部分:补充tcp连接过程

     

    在TCP/IP协议中,TCP协议提供可靠的连接服务,采用三次握手建立一个连接,如图1所示。

     (1) 第一次握手:建立连接时,客户端A发送SYN包(SYN=j)到服务器B,并进入SYN_SEND状态,等待服务器B确认。

     (2) 第二次握手:服务器B收到SYN包,必须确认客户A的SYN(ACK=j+1),同时自己也发送一个SYN包(SYN=k),即SYN+ACK包,此时服务器B进入SYN_RECV状态。

     (3) 第三次握手:客户端A收到服务器B的SYN+ACK包,向服务器B发送确认包ACK(ACK=k+1),此包发送完毕,客户端A和服务器B进入ESTABLISHED状态,完成三次握手。

    完成三次握手,客户端与服务器开始传送数据。

     

                                   图1 TCP三次握手建立连接

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

    (1)客户端A发送一个FIN,用来关闭客户A到服务器B的数据传送(报文段4)。

    (2)服务器B收到这个FIN,它发回一个ACK,确认序号为收到的序号加1(报文段5)。和SYN一样,一个FIN将占用一个序号。

    (3)服务器B关闭与客户端A的连接,发送一个FIN给客户端A(报文段6)。

    (4)客户端A发回ACK报文确认,并将确认序号设置为收到序号加1(报文段7)。

    TCP采用四次挥手关闭连接如图2所示。

     

                                   图2  TCP四次挥手关闭连接

    1.为什么建立连接协议是三次握手,而关闭连接却是四次握手呢?

    这是因为服务端的LISTEN状态下的SOCKET当收到SYN报文的连接请求后,它可以把ACK和SYN(ACK起应答作用,而SYN起同步作用)放在一个报文里来发送。但关闭连接时,当收到对方的FIN报文通知时,它仅仅表示对方没有数据发送给你了;但未必你所有的数据都全部发送给对方了,所以你可能未必会马上会关闭SOCKET,也即你可能还需要发送一些数据给对方之后,再发送FIN报文给对方来表示你同意现在可以关闭连接了,所以它这里的ACK报文和FIN报文多数情况下都是分开发送的。

     

    2.为什么TIME_WAIT状态还需要等2MSL后才能返回到CLOSED状态?

    这个问题可以参考《unix 网络编程》(第三版,2.7 TIME_WAIT状态)。

    TIME_WAIT状态由两个存在的理由。

    (1)可靠的实现TCP全双工链接的终止。

    这是因为虽然双方都同意关闭连接了,而且握手的4个报文也都协调和发送完毕,按理可以直接回到CLOSED状态(就好比从SYN_SEND状态到ESTABLISH状态那样);但是因为我们必须要假想网络是不可靠的,你无法保证你最后发送的ACK报文会一定被对方收到,因此对方处于LAST_ACK状态下的SOCKET可能会因为超时未收到ACK报文,而重发FIN报文,所以这个TIME_WAIT状态的作用就是用来重发可能丢失的ACK报文。

     (2)允许老的重复的分节在网络中消逝。

    假 设在12.106.32.254的1500端口和206.168.1.112.219的21端口之间有一个TCP连接。我们关闭这个链接,过一段时间后在 相同的IP地址和端口建立另一个连接。后一个链接成为前一个的化身。因为它们的IP地址和端口号都相同。TCP必须防止来自某一个连接的老的重复分组在连 接已经终止后再现,从而被误解成属于同一链接的某一个某一个新的化身。为做到这一点,TCP将不给处于TIME_WAIT状态的链接发起新的化身。既然 TIME_WAIT状态的持续时间是MSL的2倍,这就足以让某个方向上的分组最多存活msl秒即被丢弃,另一个方向上的应答最多存活msl秒也被丢弃。 通过实施这个规则,我们就能保证每成功建立一个TCP连接时。来自该链接先前化身的重复分组都已经在网络中消逝了。

     

    3. 为什么不能用两次握手进行连接?

    我们知道,3次握手完成两个重要的功能,既要双方做好发送数据的准备工作(双方都知道彼此已准备好),也要允许双方就初始序列号进行协商,这个序列号在握手过程中被发送和确认。
        现在把三次握手改成仅需要两次握手,死锁是可能发生的。作为例子,考虑计算机S和C之间的通信,假定C给S发送一个连接请求分组,S收到了这个分组,并发 送了确认应答分组。按照两次握手的协定,S认为连接已经成功地建立了,可以开始发送数据分组。可是,C在S的应答分组在传输中被丢失的情况下,将不知道S 是否已准备好,不知道S建立什么样的序列号,C甚至怀疑S是否收到自己的连接请求分组。在这种情况下,C认为连接还未建立成功,将忽略S发来的任何数据分 组,只等待连接确认应答分组。而S在发出的分组超时后,重复发送同样的分组。这样就形成了死锁。

     

    补充:

    a. 默认情况下(不改变socket选项),当你调用close( or closesocket,以下说close不再重复)时,如果发送缓冲中还有数据,TCP会继续把数据发送完。

    b. 发送了FIN只是表示这端不能继续发送数据(应用层不能再调用send发送),但是还可以接收数据。

    c. 应用层如何知道对端关闭?通常,在最简单的阻塞模型中,当你调用recv时,如果返回0,则表示对端关闭。在这个时候通常的做法就是也调用close,那么TCP层就发送FIN,继续完成四次握手。如果你不调用close,那么对端就会处于FIN_WAIT_2状态,而本端则会处于CLOSE_WAIT状态。这个可以写代码试试。

    d. 在很多时候,TCP连接的断开都会由TCP层自动进行,例如你CTRL+C终止你的程序,TCP连接依然会正常关闭,你可以写代码试试。

     

    插曲:

     

       特别的TIME_WAIT状态:

     

       从以上TCP连接关闭的状态转换图可以看出,主动关闭的一方在发送完对对方FIN报文的确认(ACK)报文后,会进入TIME_WAIT状态。TIME_WAIT状态也称为2MSL状态。

     

       什么是2MSL?MSL即Maximum Segment Lifetime,也就是报文最大生存时间,引用《TCP/IP详解》中的话:“它(MSL)是任何报文段被丢弃前在网络内的最长时间。”那么,2MSL也就是这个时间的2倍。其实我觉得没必要把这个MSL的确切含义搞明白,你所需要明白的是,当TCP连接完成四个报文段的交换时,主动关闭的一方将继续等待一定时间(2-4分钟),即使两端的应用程序结束。你可以写代码试试,然后用setstat查看下。

     

       为什么需要2MSL?根据《TCP/IP详解》和《The TCP/IP Guide》中的说法,有两个原因:

       其一,保证发送的ACK会成功发送到对方,如何保证?我觉得可能是通过超时计时器发送。这个就很难用代码演示了。

       其二,报文可能会被混淆,意思是说,其他时候的连接可能会被当作本次的连接。直接引用《The TCP/IP Guide》的说法:The second is to provide a “buffering period” between the end of this connection and any subsequent ones. If not for this period, it is possible that packets from different connections could be mixed, creating confusion.

     

       TIME_WAIT状态所带来的影响:

       当某个连接的一端处于TIME_WAIT状态时,该连接将不能再被使用。事实上,对于我们比较有现实意义的是,这个端口将不能再被使用。某个端口处于TIME_WAIT状态(其实应该是这个连接)时,这意味着这个TCP连接并没有断开(完全断开),那么,如果你bind这个端口,就会失败。对于服务器而言,如果服务器突然crash掉了,那么它将无法再2MSL内重新启动,因为bind会失败。解决这个问题的一个方法就是设置socket的SO_REUSEADDR选项。这个选项意味着你可以重用一个地址。

     

       对于TIME_WAIT的插曲:

       当建立一个TCP连接时,服务器端会继续用原有端口监听,同时用这个端口与客户端通信。而客户端默认情况下会使用一个随机端口与服务器端的监听端口通信。有时候,为了服务器端的安全性,我们需要对客户端进行验证,即限定某个IP某个特定端口的客户端。客户端可以使用bind来使用特定的端口。对于服务器端,当设置了SO_REUSEADDR选项时,它可以在2MSL内启动并listen成功。但是对于客户端,当使

    用bind并设置SO_REUSEADDR时,如果在2MSL内启动,虽然bind会成功,但是在windows平台上connect会失败。而在linux上则不存在这个问题。(我的实验平台:winxp, ubuntu7.10)

        要解决windows平台的这个问题,可以设置SO_LINGER选项。SO_LINGER选项决定调用close时TCP的行为。SO_LINGER涉及到linger结构体,如果设置结构体中l_onoff为非0,l_linger为0,那么调用close时TCP连接会立刻断开,TCP不会将发送缓冲中未发送的数据发送,而是立即发送一个RST报文给对方,这个时候TCP连接就不会进入TIME_WAIT状态。如你所见,这样做虽然解决了问题,但是并不安全。通过以上方式设置SO_LINGER状态,等同于设置SO_DONTLINGER状态。

     

        断开连接时的意外:

        这个算不上断开连接时的意外,当TCP连接发生一些物理上的意外情况时,例如网线断开,linux上的TCP实现会依然认为该连接有效,而windows则会在一定时间后返回错误信息。这似乎可以通过设置SO_KEEPALIVE选项来解决,不过不知道这个选项是否对于所有平台都有效。

     

    第三部分:常见面试题

      • TCP协议和UDP协议的区别是什么
        • TCP协议是有连接的,有连接的意思是开始传输实际数据之前TCP的客户端和服务器端必须通过三次握手建立连接,会话结束之后也要结束连接。而UDP是无连接的
        • TCP协议保证数据按序发送,按序到达,提供超时重传来保证可靠性,但是UDP不保证按序到达,甚至不保证到达,只是努力交付,即便是按序发送的序列,也不保证按序送到。
        • TCP协议所需资源多,TCP首部需20个字节(不算可选项),UDP首部字段只需8个字节。
        • TCP有流量控制和拥塞控制,UDP没有,网络拥堵不会影响发送端的发送速率
        • TCP是一对一的连接,而UDP则可以支持一对一,多对多,一对多的通信。
        • TCP面向的是字节流的服务,UDP面向的是报文的服务。
        • TCP介绍和UDP介绍
      • 请详细介绍一下TCP协议建立连接和终止连接的过程?
        • 助于理解的一段话
        • 两幅图(来源):
          • 建立连接:三次握手
          • image
          • 关闭连接:四次挥手
          • image
      • 三次握手建立连接时,发送方再次发送确认的必要性?
          • 主 要是为了防止已失效的连接请求报文段突然又传到了B,因而产生错误。假定出现一种异常情况,即A发出的第一个连接请求报文段并没有丢失,而是在某些网络结 点长时间滞留了,一直延迟到连接释放以后的某个时间才到达B,本来这是一个早已失效的报文段。但B收到此失效的连接请求报文段后,就误认为是A又发出一次 新的连接请求,于是就向A发出确认报文段,同意建立连接。假定不采用三次握手,那么只要B发出确认,新的连接就建立了,这样一直等待A发来数据,B的许多 资源就这样白白浪费了。
      • 四次挥手释放连接时,等待2MSL的意义?
          • 第 一,为了保证A发送的最有一个ACK报文段能够到达B。这个ACK报文段有可能丢失,因而使处在LAST-ACK状态的B收不到对已发送的FIN和ACK 报文段的确认。B会超时重传这个FIN和ACK报文段,而A就能在2MSL时间内收到这个重传的ACK+FIN报文段。接着A重传一次确认。
          • 第二,就是防止上面提到的已失效的连接请求报文段出现在本连接中,A在发送完最有一个ACK报文段后,再经过2MSL,就可以使本连接持续的时间内所产生的所有报文段都从网络中消失。

     

      • 常见的应用中有哪些是应用TCP协议的,哪些又是应用UDP协议的,为什么它们被如此设计?
        • 以下应用一般或必须用udp实现?
          • 多播的信息一定要用udp实现,因为tcp只支持一对一通信。
          • 如果一个应用场景中大多是简短的信息,适合用udp实现,因为udp是基于报文段的,它直接对上层应用的数据封装成报文段,然后丢在网络中,如果信息量太大,会在链路层中被分片,影响传输效率。
          • 如果一个应用场景重性能甚于重完整性和安全性,那么适合于udp,比如多媒体应用,缺一两帧不影响用户体验,但是需要流媒体到达的速度快,因此比较适合用udp
          • 如果要求快速响应,那么udp听起来比较合适
          • 如果又要利用udp的快速响应优点,又想可靠传输,那么只能考上层应用自己制定规则了。
          • 常见的使用udp的例子:ICQ,QQ的聊天模块。
        • 以qq为例的一个说明(转载自知乎

    登陆采用TCP协议和HTTP协议,你和好友之间发送消息,主要采用UDP协议,内网传文件采用了P2P技术。总来的说: 
    1.登陆过程,客户端client 采用TCP协议向服务器server发送信息,HTTP协议下载信息。登陆之后,会有一个TCP连接来保持在线状态。 
    2.和好友发消息,客户端client采用UDP协议,但是需要通过服务器转发。腾讯为了确保传输消息的可靠,采用上层协议来保证可靠传输。如果消息发送失败,客户端会提示消息发送失败,并可重新发送。 
    3.如果是在内网里面的两个客户端传文件,QQ采用的是P2P技术,不需要服务器中转。

    image

    展开全文
  • 在建立TCP的过程中,会用到三次握手和四次挥手,三次握手和四...那么在TCP协议编程的过程中,哪一步用到了三次握手四次挥手?通过一张图来看一下: 这是一个利用TCP构建的一个C/S模型,这里只做简略介绍(Java构建C...

    在建立TCP的过程中,会用到三次握手和四次挥手,三次握手和四次挥手到底是什么?在哪里用到?

    简介

      确切的说在Java的socket编程中,是不用关心三次握手和四次挥手的,这是TCP/IP分层中的传输层需要完成的事情,但是作为原理是有必要了解的
      那么在TCP协议编程的过程中,哪一步用到了三次握手四次挥手?通过一张图来看一下:
    在这里插入图片描述
      这是一个利用TCP构建的一个C/S模型,这里只做简略介绍(Java构建C/S),服务器端需要完成绑定端口,监听并返回客户端发来的连接,读写,然后关闭资源。客户端需要连接服务器端,读写,关闭资源。
      从图上可以看到,在客户端发起的connect过程中,服务器端一直等待accpet中,发生了三次握手,也就是只有通过三次握手,这次连接才能建立。
    在服务器端和客户端关闭资源的过程中,发生了四次挥手,也就是说,当四次挥手完成后,服务器端和客户端才可以安全的退出。

    首先需要了解TCP的文段格式
    TCP头部的这张图放在这里以作参考
    在这里插入图片描述
    源端口和目的端口:各占2个字节,分别写入源端口和目的端口;

    序号:占4个字节,TCP连接中传送的字节流中的每个字节都按顺序编号。例如,一段报文的序号 字段值是 301 ,而携带的数据共有100字段,显然下一个报文段(如果还有的话)的数据序号应该从401开始;

    确认号:占4个字节,是期望收到对方下一个报文的第一个数据字节的序号。例如,B收到了A发送过来的报文,其序列号字段是501,而数据长度是200字节,这表明B正确的收到了A发送的到序号700为止的数据。因此,B期望收到A的下一个数据序号是701,于是B在发送给A的确认报文段中把确认号置为701;

    数据偏移:占4位,它指出TCP报文的数据距离TCP报文段的起始处有多远;

    保留:占6位,保留今后使用,但目前应都位0;

    紧急URG:当URG=1,表明紧急指针字段有效。告诉系统此报文段中有紧急数据;

    确认ACK:仅当ACK=1时,确认号字段才有效。TCP规定,在连接建立后所有报文的传输都必须把ACK置1;

    推送PSH:当两个应用进程进行交互式通信时,有时在一端的应用进程希望在键入一个命令后立即就能收到对方的响应,这时候就将PSH=1;

    复位RST:当RST=1,表明TCP连接中出现严重差错,必须释放连接,然后再重新建立连接;

    同步SYN:在连接建立时用来同步序号。当SYN=1,ACK=0,表明是连接请求报文,若同意连接,则响应报文中应该使SYN=1,ACK=1;

    终止FIN:用来释放连接。当FIN=1,表明此报文的发送方的数据已经发送完毕,并且要求释放;
    窗口,占2字节,指的是通知接收方,发送本报文你需要有多大的空间来接受;

    检验和:占2字节,校验首部和数据这两部分;

    紧急指针:占2字节,指出本报文段中的紧急数据的字节数;

    三次握手

      TCP是传递信息首先需要建立连接,就和打电话一样,首先需要互相表明身份后才可以继续通话。

    为什么需要三次握手呢?

    1.第一种理解:
      客户端给服务器端发送了一个消息,服务器端收到了消息。这个时候服务器端可以知道客户端可以发送消息了,服务器自己可以接收消息了,但是不知道服务器自己是否可以发消息,也不知道客户端是否可以接收消息,客户端是什么都不知道。这是第一次握手
      第一次握手完成后,服务器端向客户端发送了确认消息,客户端收到后。服务器端知道了服务器自己可以接收发送消息,客户端可以发送消息。客户端知道了自己可以接收发送消息,也知道了服务器端可以接收发送消息。这就是第二次握手,但是这个时候服务器端是不知道客户端是否可以接收消息 ,所以需要第三次握手。
      第三次握手客户端再次给服务器端发送确认消息,服务器端综合以前的消息,并且在这次确认中知道了客户端可以接收消息,连接建立完成。

    2.第二种理解:
      也可以这样理解,在客户端给服务器端发送完成消息后就下线了,服务器端接收到客户端的消息后,会给客户端发送一条确认消息,如果这个时候连接建立的话,服务端是不知道客户端是否能正确到确认消息。

    3.第三种理解:
      就是为了让对方知道数据到底是从哪里开始的,seq是多少就决定了数据是从哪里开始的,知道后给对端进行回应

    通过底层原理来了解一下三次握手是如何建立的

    在这里插入图片描述

    第一次握手

      整个过程是由客户端发起的,也就是connect,将SYN置为1,SYN就是建立时用来同步序号的,seq是客户端随机的一个值,代表传输的序号。发送完毕客户端进入SYN-SENT状态。

    第二次握手

      服务器端在接收到数据之前一直处于LISTEN状态,接收到消息后,会给客户端回一条消息进行第二次握手,这时SYN置为1,用于建立连接,ACK=1,这个是确认用的,只有ACK=1时确认序号才会生效,ack也就是确认序号=x+1,就是客户端发给服务器端的序号加1,并生成一个随机的序号y,然后将这条消息发送给客户端,发送完毕进入SYN-RCVD状态。

    第三次握手

      客户端接收到服务器端的回复后,会给服务器端回一条确认消息,发出消息后客户端就意味着三次握手已经完成,所以消息中SYN没有置为1,只是确认信息,ACK=1,确认序号ack=y+1。算上第一次客户端给服务器端发消息,这是第二次,第一次seq=x,所以这次是seq=x+1。发送完消息进入ESTAB-LISHED状态。注意seq只是一个序号,只是第一次随机生成的,生成后,以后每次发消息都是加1,最大为65535,达到这个数字后又重新从0开始。
      TCP规定第三次握手是可以携带数据的
      服务器端接收到这个确认信息后,也进入ESTABL-LISHED状态,整个连接就建立了。

    四次挥手

    四次挥手在socket编程中,就是任意一方调用close的过程
    在这里插入图片描述

    第一次挥手

      客户端发起第一次挥手,FIN置为1,序号seq是传输数据的最后一个序号值加1,为u,发送完后客户端进入FIN-WAIT-1

    第二次挥手

      服务器端接收到客户端的关闭消息后,会通知应用程序关闭,然后会给客户端回一条确认消息,ACK置为1,确认序号ack=u+1,本次消息的序号为seq=v,发送完消息后,进入CLOSE-WAIT状态。客户端接收到服务器端的确认信息后,进入FIN-WAIT-2。
      需要注意的是进入CLOSE-WAIT状态的服务器还是可以给客户端发送消息的,客户端也可以接受到服务端发送的消息

    第三次挥手

      服务器端被动关闭,这时会给客户端发送一条关闭确认信息,FIN置为1,ACK=1,确认序号不变,还是u+1,由于可能在半关闭状态下服务器可能给客户端发送了一些消息,所以本次消息序号为w。发送完毕后服务器端进入LAST-ACK,等待确认

    第四次挥手

      客户端收到服务器端的关闭消息后,会回一条确认信息,ACK=1,ack=w+1,seq=u+1。在2MSL后客户端关闭,服务器端接收到确认信息后也会关闭。

    为什么需要等待2MSL后才关闭

    MSL为最长报文段寿命,规定MSL为2分钟,Linux下MSL为30秒

    等待的原因:

    1. 为了让对端有足够的时间接受到ACK包,如果对端没有接收到ACK包,那么会导致对端重发FIN,一来一去就是2MSL
    2. 为了避免新旧连接混肴,有些路由器会缓存IP包,如果连接被重用了,这些延迟的包就会和后面的混在一起
    为什么需要四次挥手

      因为TCP是全双工的,也就是说在同一时刻不论是客户端还是服务端都可以同时发送消息和接受消息,发送方和接收方都需要FIN和ACK,一个两次,看起来也就是四次了。

    服务器端出现大量CLOSE_WAIT状态的原因

      对方关闭socket后,我方忙于读或者写,没有及时关闭连接,主要问题可能是在代码中没有及时的释放资源

    展开全文
  • 两张动图-彻底明白TCP的三次握手四次挥手

    万次阅读 多人点赞 2017-06-04 21:53:54
    为什么建立连接是三次握手,关闭连接确是四次挥手呢? 建立连接的时候, 服务器在LISTEN状态下,收到建立连接请求的SYN报文后,把ACK和SYN放在一个报文里发送给客户端。 而关闭连接时,服务器收到对方的FIN报文时,...

    背景描述

    通过上一篇中网络模型中的IP层的介绍,我们知道网络层,可以实现两个主机之间的通信。但是这并不具体,因为,真正进行通信的实体是在主机中的进程,是一个主机中的一个进程与另外一个主机中的一个进程在交换数据。IP协议虽然能把数据报文送到目的主机,但是并没有交付给主机的具体应用进程。而端到端的通信才应该是应用进程之间的通信。

    UDP,在传送数据前不需要先建立连接,远地的主机在收到UDP报文后也不需要给出任何确认。虽然UDP不提供可靠交付,但是正是因为这样,省去和很多的开销,使得它的速度比较快,比如一些对实时性要求较高的服务,就常常使用的是UDP。对应的应用层的协议主要有 DNS,TFTP,DHCP,SNMP,NFS 等。

    TCP,提供面向连接的服务,在传送数据之前必须先建立连接,数据传送完成后要释放连接。因此TCP是一种可靠的的运输服务,但是正因为这样,不可避免的增加了许多的开销,比如确认,流量控制等。对应的应用层的协议主要有 SMTP,TELNET,HTTP,FTP 等。


    常用的熟知端口号

    应用程序FTPTFTPTELNETSMTPDNSHTTPSSHMYSQL
    熟知端口21,206923255380223306
    传输层协议TCPUDPTCPTCPUDPTCPTCPTCP

    TCP的概述

    TCP把连接作为最基本的对象,每一条TCP连接都有两个端点,这种断点我们叫作套接字(socket),它的定义为端口号拼接到IP地址即构成了套接字,例如,若IP地址为192.3.4.16 而端口号为80,那么得到的套接字为192.3.4.16:80。

    TCP报文首部

    1. 源端口和目的端口,各占2个字节,分别写入源端口和目的端口;
    2. 序号,占4个字节,TCP连接中传送的字节流中的每个字节都按顺序编号。例如,一段报文的序号字段值是 301 ,而携带的数据共有100字段,显然下一个报文段(如果还有的话)的数据序号应该从401开始;
    3. 确认号,占4个字节,是期望收到对方下一个报文的第一个数据字节的序号。例如,B收到了A发送过来的报文,其序列号字段是501,而数据长度是200字节,这表明B正确的收到了A发送的到序号700为止的数据。因此,B期望收到A的下一个数据序号是701,于是B在发送给A的确认报文段中把确认号置为701;
    4. 数据偏移,占4位,它指出TCP报文的数据距离TCP报文段的起始处有多远;
    5. 保留,占6位,保留今后使用,但目前应都位0;
    6. 紧急URG,当URG=1,表明紧急指针字段有效。告诉系统此报文段中有紧急数据;
    7. 确认ACK,仅当ACK=1时,确认号字段才有效。TCP规定,在连接建立后所有报文的传输都必须把ACK置1;
    8. 推送PSH,当两个应用进程进行交互式通信时,有时在一端的应用进程希望在键入一个命令后立即就能收到对方的响应,这时候就将PSH=1;
    9. 复位RST,当RST=1,表明TCP连接中出现严重差错,必须释放连接,然后再重新建立连接;
    10. 同步SYN,在连接建立时用来同步序号。当SYN=1,ACK=0,表明是连接请求报文,若同意连接,则响应报文中应该使SYN=1,ACK=1;
    11. 终止FIN,用来释放连接。当FIN=1,表明此报文的发送方的数据已经发送完毕,并且要求释放;
    12. 窗口,占2字节,指的是通知接收方,发送本报文你需要有多大的空间来接受;
    13. 检验和,占2字节,校验首部和数据这两部分;
    14. 紧急指针,占2字节,指出本报文段中的紧急数据的字节数;
    15. 选项,长度可变,定义一些其他的可选的参数。

    TCP连接的建立(三次握手)

    这里写图片描述

    最开始的时候客户端和服务器都是处于CLOSED状态。主动打开连接的为客户端,被动打开连接的是服务器。

    1. TCP服务器进程先创建传输控制块TCB,时刻准备接受客户进程的连接请求,此时服务器就进入了LISTEN(监听)状态;
    2. TCP客户进程也是先创建传输控制块TCB,然后向服务器发出连接请求报文,这是报文首部中的同部位SYN=1,同时选择一个初始序列号 seq=x ,此时,TCP客户端进程进入了 SYN-SENT(同步已发送状态)状态。TCP规定,SYN报文段(SYN=1的报文段)不能携带数据,但需要消耗掉一个序号。
    3. TCP服务器收到请求报文后,如果同意连接,则发出确认报文。确认报文中应该 ACK=1,SYN=1,确认号是ack=x+1,同时也要为自己初始化一个序列号 seq=y,此时,TCP服务器进程进入了SYN-RCVD(同步收到)状态。这个报文也不能携带数据,但是同样要消耗一个序号。
    4. TCP客户进程收到确认后,还要向服务器给出确认。确认报文的ACK=1,ack=y+1,自己的序列号seq=x+1,此时,TCP连接建立,客户端进入ESTABLISHED(已建立连接)状态。TCP规定,ACK报文段可以携带数据,但是如果不携带数据则不消耗序号。
    5. 当服务器收到客户端的确认后也进入ESTABLISHED状态,此后双方就可以开始通信了。
      三次握手

    为什么TCP客户端最后还要发送一次确认呢?

    一句话,主要防止已经失效的连接请求报文突然又传送到了服务器,从而产生错误。

    如果使用的是两次握手建立连接,假设有这样一种场景,客户端发送了第一个请求连接并且没有丢失,只是因为在网络结点中滞留的时间太长了,由于TCP的客户端迟迟没有收到确认报文,以为服务器没有收到,此时重新向服务器发送这条报文,此后客户端和服务器经过两次握手完成连接,传输数据,然后关闭连接。此时此前滞留的那一次请求连接,网络通畅了到达了服务器,这个报文本该是失效的,但是,两次握手的机制将会让客户端和服务器再次建立连接,这将导致不必要的错误和资源的浪费。

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

    TCP连接的释放(四次挥手)

    这里写图片描述

    数据传输完毕后,双方都可释放连接。最开始的时候,客户端和服务器都是处于ESTABLISHED状态,然后客户端主动关闭,服务器被动关闭。

    1. 客户端进程发出连接释放报文,并且停止发送数据。释放数据报文首部,FIN=1,其序列号为seq=u(等于前面已经传送过来的数据的最后一个字节的序号加1),此时,客户端进入FIN-WAIT-1(终止等待1)状态。 TCP规定,FIN报文段即使不携带数据,也要消耗一个序号。
    2. 服务器收到连接释放报文,发出确认报文,ACK=1,ack=u+1,并且带上自己的序列号seq=v,此时,服务端就进入了CLOSE-WAIT(关闭等待)状态。TCP服务器通知高层的应用进程,客户端向服务器的方向就释放了,这时候处于半关闭状态,即客户端已经没有数据要发送了,但是服务器若发送数据,客户端依然要接受。这个状态还要持续一段时间,也就是整个CLOSE-WAIT状态持续的时间。
    3. 客户端收到服务器的确认请求后,此时,客户端就进入FIN-WAIT-2(终止等待2)状态,等待服务器发送连接释放报文(在这之前还需要接受服务器发送的最后的数据)
    4. 服务器将最后的数据发送完毕后,就向客户端发送连接释放报文,FIN=1,ack=u+1,由于在半关闭状态,服务器很可能又发送了一些数据,假定此时的序列号为seq=w,此时,服务器就进入了LAST-ACK(最后确认)状态,等待客户端的确认。
    5. 客户端收到服务器的连接释放报文后,必须发出确认,ACK=1,ack=w+1,而自己的序列号是seq=u+1,此时,客户端就进入了TIME-WAIT(时间等待)状态。注意此时TCP连接还没有释放,必须经过2 ∗ * MSL(最长报文段寿命)的时间后,当客户端撤销相应的TCB后,才进入CLOSED状态。
    6. 服务器只要收到了客户端发出的确认,立即进入CLOSED状态。同样,撤销TCB后,就结束了这次的TCP连接。可以看到,服务器结束TCP连接的时间要比客户端早一些。

    四次挥手

    为什么客户端最后还要等待2MSL?

    MSL(Maximum Segment Lifetime),TCP允许不同的实现可以设置不同的MSL值。

    第一,保证客户端发送的最后一个ACK报文能够到达服务器,因为这个ACK报文可能丢失,站在服务器的角度看来,我已经发送了FIN+ACK报文请求断开了,客户端还没有给我回应,应该是我发送的请求断开报文它没有收到,于是服务器又会重新发送一次,而客户端就能在这个2MSL时间段内收到这个重传的报文,接着给出回应报文,并且会重启2MSL计时器。

    第二,防止类似与“三次握手”中提到了的“已经失效的连接请求报文段”出现在本连接中。客户端发送完最后一个确认报文后,在这个2MSL时间中,就可以使本连接持续的时间内所产生的所有报文段都从网络中消失。这样新的连接中不会出现旧连接的请求报文。

    为什么建立连接是三次握手,关闭连接确是四次挥手呢?

    建立连接的时候, 服务器在LISTEN状态下,收到建立连接请求的SYN报文后,把ACK和SYN放在一个报文里发送给客户端。
    而关闭连接时,服务器收到对方的FIN报文时,仅仅表示对方不再发送数据了但是还能接收数据,而自己也未必全部数据都发送给对方了,所以己方可以立即关闭,也可以发送一些数据给对方后,再发送FIN报文给对方来表示同意现在关闭连接,因此,己方ACK和FIN一般都会分开发送,从而导致多了一次。

    如果已经建立了连接,但是客户端突然出现故障了怎么办?

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




    展开全文
  • TCP的三次握手四次挥手详解

    万次阅读 多人点赞 2018-05-14 14:22:00
    TCP是主机对主机层的传输控制协议,提供可靠的连接服务,采用三次握手确认建立一个连接,与之相反的,采用四次挥手来断开连接: TCP标志位有6种标示,即:SYN(建立联机) 、 ACK(确认) 、 PSH(传送) 、 FIN(f结束) ...

    TCP是主机对主机层的传输控制协议,提供可靠的连接服务,采用三次握手确认建立一个连接,与之相反的,采用四次挥手来断开连接:
    TCP标志位有6种标示,即:SYN(建立联机) 、 ACK(确认) 、 PSH(传送) 、 FIN(f结束) 、 RST(重置) 、 URG(紧急) 、 Sequence number(顺序号码) 、 Acknowledge number(确认号码)。

    三次握手

    为了准确无误的将数据发送到指定IP处,TCP协议采用了三次握手的策略,如下步骤所示:
    1、客户端采用TCP协议将带有SYN标志的数据包发送给服务器,等待服务器的确认。
    2、服务器端在收到SYN的数据包后,必须确认SYN,即自己发送的ACK标志,同时,自己也将会向客户端发送一个SYN标志。
    3、客户端在接收到服务器短的SYN+ACK包后,自己会向服务器发送ACK包,完成三次握手。那么客户端和服务器正式建立了连接,开始传输数据。
    三次握手的图如下所示:
    三次握手的图

    四次挥手

    四次挥手是用来断开服务器和客户端之间的通信的,之所以要断开连接,是因为TCP/IP 协议是要占用端口号的,而计算机的端口却是有限的,不进行断开的话,势必会造成计算机资源的浪费。
    1、在整个通信的过程中,谁先发起请求,谁就是客户端。
    当客户端的数据传输到尾部时,客户端向服务器发送带有FIN标志的数据包,使其明白自己准备断开通信了。
    2、因为TCP的通信是使用全双工通信的WebSocket,所以在断开连接的时候也应该是双向的;当服务器收到带有FIN标志的数据包时,其必不会直接发送FIN标志断开通信的请求,而是先发送一个带有ACK标志的应答信息,使客户端明白服务器还有数据要进行发送。
    3、当 服务器的数据发送完成后,向客户端发送带有FIN标志的数据包,通知客户端断开连接。
    4、这一次挥手是我觉得四次挥手中设计的最巧妙的一次。
    当客户端收到FIN后,担心网络上某些不可控制的因素导致服务器不知道他要断开连接,会发送ACK进行确认,同时把自己设置成TIME_WAIT状态并启动定时器,**在TCP的定时器到达后客户端并没有接收到请求,会重新发送;当服务器收到请求后就断开连接;当客户端等待2MLS(两倍报文最大生存时间)后,没有收到请求重传的请求后,客户端这边就断开连接,**整个TCP通信就结束了。
    四次挥手的图如下所示:
    四次挥手

    注:三次握手为什么不能改成两次握手?

    解:三次握手中的每一次都是必须的。如果是两次握手,在第二次结束后,服务器并不能保证客户端已经收到了第二次的请求,如此一来的话,服务器会一直保存着这个通信过程,因为TCP通信都是要占用端口的,造成了一定的资源浪费。所以,就一定要让客户端来发送ACK的确认请求。

    注:关闭的时候为什么会是四次挥手?

    解:四次挥手不能像三次握手一样,三次握手可以将ACK+SYN 一起发送,ACK用于确认信息,SYN却是用来建立联机的;四次挥手中ACK是不能和FIN一起发送,ACK只是告诉客户端确认我收到了,等我将数据发送完毕之后会向其发送FIN的标志,所以四次挥手是不能够改变的。

    以上就是我对三次握手和四次挥手的理解,欢迎我们一起来讨论。

    展开全文
  • 6-第六次实验-wireshark抓包图解TCP三次握手四次挥手详解.docx
  • TCP三次握手四次挥手详解及常见面试题

    万次阅读 多人点赞 2018-05-24 11:51:38
    每发送一数据,就累加一该数据字节数的大小。 注意:序列号不会从0或1开始,而是在建立连接时由计算机生成的一个随机数作为其初始值,通过SYN包发送给接收端主机。然后再将每转发过去的字节数累加到初始值上...
  • 三次握手】 第一次握手:Client端会发送一个SYN标记为1的包,并随机取了一个随机数SEQ©=x为自己的初始序列号,发送完后进入SYN-SEND状态。 第二次握手:Server端收到了SYN=1的标记,知道了Client端想要和自己建立...
  • TCP三次握手的过程如下: 建立TCP连接,就是指建立一个TCP连接时,需要客户端和服务端总共发送3个包以确认连接的建立。在socket编程中,这一过程由客户端执行connect来触发。 在TCP/IP协议中,TCP协议提供可靠的连接...
  • 详解三次握手四次挥手(一看就懂哦)

    万次阅读 多人点赞 2018-06-28 16:28:47
    建立TCP需要三次握手才能建立,而断开连接则需要次握手。整个过程如下图所示:先来看看如何建立连接的。首先Client端发送连接请求报文,Server段接受连接后回复ACK报文,并为这次连接分配资源。Client端接收到ACK...
  • TCP 三次握手四次挥手详解

    千次阅读 2018-12-26 15:37:09
    所谓三次握手(Three-way Handshake),是指建立一个TCP连接时,需要客户端和服务器总共发送3个包。 三次握手的目的是连接服务器指定端口,建立TCP连接,并同步连接双方的序列号和确认号并交换 TCP窗口大小信息。 在...
  • 文章目录一.TCP简介二.TCP数据报结构三.TCP的三次握手四.TCP的四次挥手 一.TCP简介 TCP(Transmission Control Protocol,传输控制协议)是一种面向连接的、可靠的、基于字节流的通信协议,数据在传输前要建立连接...
  • 该标志仅在三次握手建立TCP连接时有效。它提示TCP连接的服务端检查序列编号,该序列编号为TCP连接初始端(一般是客户端)的初始序列编号。其实就是客户端的初始序列编号。 ACK:确认标志 确认编号(Acknowledgement ...
  • 三次握手四次挥手详解,觉得本博文写的很好,分享给正在学习或者学习完还对TCP的三次握手和四次挥手还不熟悉的人,相信看完之后就能明白了。
  • 为什么建立连接是三次握手,关闭连接确是四次挥手呢? 建立连接的时候, 服务器在LISTEN状态下,收到建立连接请求的SYN报文后,把ACK和SYN放在一个报文里发送给客户端。  而关闭连接时,服务器收到对方的FIN...
  •  TCP/IP协议的详细信息参看《TCP/IP协议详解卷本。下面是TCP报文格式图: 图1 TCP报文格式  上图中有几个字段需要重点介绍下:  (1)序号:seq序号,占32位,用来标识从TCP源端向目的端发送的字节流,发起方...
  • 面试官,不要再问我三次握手四次挥手

    万次阅读 多人点赞 2019-10-08 09:55:58
    三次握手四次挥手是各个公司常见的考点,也具有一定的水平区分度,也被一些面试官作为热身题。很多小伙伴说这个问题刚开始回答的挺好,但是后面越回答越冒冷汗,最后就歇菜了。 见过比较典型的面试场景是这样的: ...
  • 目录 TCP协议简介 TCP报头 TCP工作原理 科来解码详解 wireshark解码详解 三次握手四次挥手 数据包的大致结构 你不知道的三次握手 为什么需要有三次握手? 为啥只有三次握手才能确认双方的接受与发送能力是否正常,...
  • 3.1TCP编程中三次握手四次挥手的全过程 3.2TCP状态转换图 1、三次握手 1.1connect()、listen()和accept()三者之间的关系 在我之前的一篇博文中就有详细的提到过TCP的编程流程TCP详解及编程流..

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 9,550
精华内容 3,820
关键字:

三次握手四次挥手详解