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

    一、网络模型

    网络模型一般是指OSI七层参考模型TCP/IP四层参考模型。这两个模型在网络中应用最为广泛。

    提问:各层的网络协议有哪些?(以下只是部分)

    • 应用层:HTTP、SMTP、SSH
    • 传输层:TCP、UDP 
    • 网络层:IP、路由表
    • 网络接口层:以太网

    二、TCP/IP协议数据流

    三、TCP连接

    1、TCP连接的特点:

    • 面向连接的、可靠的传输协议
    • TCP连接不是物理连接(不是电线的两端连接),只有建立TCP连接之后,客户端和服务端才可以开辟资源,比如建立Socket连接。
    • 用户进程与服务器进程完成一次通信都需要完成三个阶段:建立连接、传输数据、断开连接。
    • TCP建立连接需要三次握手,断开连接需要四次挥手。

    2、TCP连接过程

    (本文暂时跳过了序列号seq和确认号ack的讲解,只讲以下3个标志位)

    (1)标志位

    • SYN(Synchronize):发起建立连接的标志。
    • ACK(Acknowledge):确认/应答的标志。
    • FIN(Finally):发起断开连接的标志。

    (2)TCP连接的两端

    • 客户端:主动打开/关闭连接的一方。
    • 服务端:被动打开/关闭连接的一方。

    (3)三次握手过程:

    • 第一次握手:客户端首先发送一个带有SYN的报文给服务端,表示请求建立连接,并进入SYN-SENT(同步已发送)状态,等待服务端确认。
    • 第二次握手:服务端发送一个带有SYN+ACK的报文给客户端,表示收到并确认客户端发送的连接请求报文,同时服务端也请求和客户端建立连接,此时服务端进入SYN-RCVD(同步收到)状态。
    • 第三次握手:客户端会再一次发送一个带有ACK的报文给服务端,表示客户端也确认收到服务端的应答和连接请求报文。当服务端收到报文后,客户端和服务端进入ESTAB-LISHED(已建立连接)状态,至此完成三次握手,双方正式建立了连接通信,可以进行数据传输。

    提问:为什么TCP建立连接是三次握手而不能是两次握手?

    通信是双向的,目的是为了双方彼此建立可靠的连接。如果仅仅是两次握手,仅客户端能够确认服务端的应答,而服务端无法确认客户端是否收到服务端的连接请求,所以客户端仍需再一次发送ACK报文给服务端表示应答,服务端收到后双方才算正式建立连接通信。

    (4)四次挥手过程:

    • 第一次挥手:客户端首先发送一个带有FIN的报文给服务端,表示请求断开连接,即客户端已经没有数据要发送了,此时客户端进入FIN-WAIT-1(终止等待1)状态。
    • 第二次挥手:服务端发送一个带有ACK的报文给客户端,表示确认收到客户端的断开连接请求报文,此时服务端进入CLOSE-WAIT(关闭等待)状态。客户端收到服务端的应答后,客户端就进入FIN-WAIT-2(终止等待2)状态。这个时候如果服务端继续发送数据,客户端依然要接受。
    • 第三次挥手:服务端在最后的数据发送完毕后,会再次发送一个带有FIN+ACK的报文给客户端,表示服务端此时同意断开连接,并向客户端请求断开连接,此时服务端进入LAST-ACK(最后确认)状态。
    • 第四次挥手:客户端再次收到服务端的应答和断开连接请求报文后,会再一次发送一个带有ACK的报文给服务端,表示客户端也确认收到服务端的断开连接请求,此时客户端就进入了TIME-WAIT(时间等待)状态,当服务端收到客户端的应答报文后,就立刻进入CLOSED(关闭连接)状态,而客户端必须经过2MSL(最长报文段寿命)的时间、并且这个期间没有再次收到FIN报文,才进入CLOSED状态。可以看到,服务端结束TCP连接的时间要比客户端早一些。

    提问:为什么TCP断开连接需要四次挥手?

    因为TCP连接建立的是可靠的连接。当服务端收到FIN报文后,很可能不会立即关闭Socket,因为此时服务端的数据传输可能还没发送完毕,所以此时只能先回一个ACK报文,告诉客户端:“你发的FIN报文我收到了,只有等我所有数据都发送完毕,我才能发送FIN报文给你”。因此不能在第二次挥手的时候就一起发送ACK+FIN报文,故需要四次挥手。

    提问:为什么客户端TIME_WAIT状态需要等待2MSL(最大报文段生存时间)才能进入CLOSE状态? 

    假设网络是不可靠的,有可能客户端最后发送的ACK报文丢失,此时服务端没有收到客户端的应答,会不断发送FIN报文给客户端,所以TIME-WAIT状态就是客户端用来重发可能丢失的ACK报文,它必须确认服务端收到了ACK报文。客户端会设置一个计时器,等待2MSL的时间,如果在该时间内再次收到FIN报文,客户端会重发ACK数据并再次等待2MSL,直到这2MSL时间内都没收到服务端的FIN报文,客户端才推断ACK报文被服务端成功接收,此时才结束客户端的TCP连接。

    (所谓的2MSL是指两倍的MSL(Maximum Segment Lifetime)。MSL指一个片段在网络中最大的存活时间,2MSL就是一个发送和一个回复所需的最长时间)

    补充:知乎上有个形象的示例,再次说明TCP连接为什么是三次握手,而不是两次或四次?

  • 相关阅读:
    Linux scp、ssh命令
    Linux ps、top、free、uname命令
    适配器模式
    Linux不能进入图形化界面运行yum不管用
    SpringMVC 测试 mockMVC
    Idea和Git集成,并且Git管理不同的秘钥,idea分别提交项目到GitLab和GitHub
    多线程
    Java中Volatile关键字详解
    Spring事务管理--(二)嵌套事物详解
    jConsole, jVisualvm, btrace 区别和联系
  • 原文地址:https://www.cnblogs.com/ZekiChen/p/12370752.html
Copyright © 2011-2022 走看看