V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Distributions
Ubuntu
Fedora
CentOS
中文资源站
网易开源镜像站
enocher
V2EX  ›  Linux

图解 TCP 三次握手与四次挥手

  •  1
     
  •   enocher · 2017-07-12 14:13:56 +08:00 · 7133 次点击
    这是一个创建于 2698 天前的主题,其中的信息可能已经有所发展或是发生改变。

    引言

    TCP 三次握手和四次挥手不管是在开发还是面试中都是一个非常重要的知识点,它是我们优化 web 程序性能的基础。但是大部分教材都对这部分解释的比较抽象,本文我们就利用 wireshark 来抓包以真正体会整个流程的细节。

    三次握手

    根据下面这幅图我们来看一下 TCP 三次握手。p.s: 每个箭头代表一次握手。

    tcp 三次握手

    第一次握手

    client 发送一个SYN(J)包给 server,然后等待 server 的 ACK 回复,进入SYN-SENT状态。p.s: SYN 为 synchronize 的缩写,ACK 为 acknowledgment 的缩写。

    第二次握手

    server 接收到 SYN(seq=J)包后就返回一个ACK(J+1)包以及一个自己的**SYN(K)**包,然后等待 client 的 ACK 回复,server 进入SYN-RECIVED状态。

    第三次握手

    client 接收到 server 发回的 ACK(J+1)包后,进入ESTABLISHED状态。然后根据 server 发来的 SYN(K)包,返回给等待中的 server 一个ACK(K+1)包。等待中的 server 收到 ACK 回复,也把自己的状态设置为ESTABLISHED。到此 TCP 三次握手完成,client 与 server 可以正常进行通信了。

    为什么要进行三次握手

    我们来看一下为什么需要进行三次握手,两次握手难道不行么?这里我们用一个生活中的具体例子来解释就很好理解了。我们可以将三次握手中的客户端和服务器之间的握手过程比喻成 A 和 B 通信的过程:

    • 在第一次通信过程中,A 向 B 发送信息之后,B 收到信息后可以确认自己的收信能力和 A 的发信能力没有问题。
    • 在第二次通信中,B 向 A 发送信息之后,A 可以确认自己的发信能力和 B 的收信能力没有问题,但是 B 不知道自己的发信能力到底如何,所以就需要第三次通信。
    • 在第三次通信中,A 向 B 发送信息之后,B 就可以确认自己的发信能力没有问题。

    wireshark

    上面分析还不够形象,很容易忘记,下面我们利用 wireshark 来证明一下上面的分析过程。从下面的的输出就可以很容易看出来,必须要经过前面的三次 tcp 请求才会有起一次 http 请求。

    第一次请求客户端发送一个 SYN 包,序列号是 0。

    wireshark-tcp-01

    第二次请求服务器会发送一个 SYN 和一个 ACK 包,序列号是 0,ack 号是 1。

    wireshark-tcp-02

    第三次本地客户端请求会发送一个 ACK 包,序列号是 1,ack 号是 1 来回复服务器。

    wireshark-tcp-03

    四次挥手

    以下面这张图为例,我们来分析一下 TCP 四次挥手的过程。

    tcp 四次挥手

    第一次挥手

    client 发送一个FIN(M)包,此时 client 进入FIN-WAIT-1状态,这表明 client 已经没有数据要发送了。

    第二次挥手

    server 收到了 client 发来的 FIN(M)包后,向 client 发回一个ACK(M+1)包,此时 server 进入CLOSE-WAIT状态,client 进入FIN-WAIT-2状态。

    第三次挥手

    server 向 client 发送FIN(N)包,请求关闭连接,同时 server 进入LAST-ACK状态。

    第四次挥手

    client 收到 server 发送的 FIN(N)包,进入TIME-WAIT状态。向 server 发送**ACK(N+1)**包,server 收到 client 的 ACK(N+1)包以后,进入CLOSE状态; client 等待一段时间还没有得到回复后判断 server 已正式关闭,进入CLOSE状态。

    References

    TCP-CONNECTION TCP-TERMINATION

    公众号

    欢迎大家关注我的公众号ziwenxie_mj订阅我博客上的原创文章 :)

    id 是 ziwenxie_mj

    p.s: 如有错误,还望指正 :)

    44 条回复    2017-07-14 16:09:29 +08:00
    est
        1
    est  
       2017-07-12 14:17:51 +08:00
    LZ 放心。在公众号写技术文章没人看的。
    introom
        2
    introom  
       2017-07-12 14:44:48 +08:00 via Android
    @est 写鸡汤?
    SKull4
        3
    SKull4  
       2017-07-12 14:58:21 +08:00
    每次握手,回首出现了问题会怎样
    zealot0630
        4
    zealot0630  
       2017-07-12 16:56:32 +08:00
    "为什么要进行三次握手" 这个问题回答到并不好 我只能给 4/10 分
    zealot0630
        5
    zealot0630  
       2017-07-12 16:58:33 +08:00
    三次握手其中一个功能是防 DDOS,先领会到这里能拿及格分
    ibufu
        6
    ibufu  
       2017-07-12 17:02:13 +08:00
    还以为是来讲笑话的
    enocher
        7
    enocher  
    OP
       2017-07-12 17:07:28 +08:00
    @SKull4 以第三次客户端没有发送给服务器 ack 请求为例子,这里涉及到超时和重传机制,这个时候服务器没法进入 ESTABLISHED 状态,如果超过一定时间服务器后向客户端发送 RTS 报文,同时进入 CLOSED 状态。深入一点也可以去了解一下 syn 攻击之类的 :)
    ajan
        8
    ajan  
       2017-07-12 17:18:04 +08:00
    完全没有在微信里看文章的癖好~
    Geoion
        9
    Geoion  
       2017-07-12 17:20:13 +08:00   ❤️ 2
    没人会在公众号看技术文章的,据我观察在朋友圈转发技术文章的,都是没有女朋友的。
    araraloren
        10
    araraloren  
       2017-07-12 17:24:45 +08:00
    MARK

    @est 还行,只要文章好还是有人看的,我就关注了 CloudMan,写的关于云和容器的东西还不错,每天 5 分钟。。
    Chingim
        11
    Chingim  
       2017-07-12 17:37:27 +08:00 via Android
    @zealot0630 如何防 ddos,期待展开
    woshixiaohao1982
        12
    woshixiaohao1982  
       2017-07-12 17:42:18 +08:00
    @zealot0630 #5 ddos 实际上 根本防不了,链路层上 就打垮你了
    panda1001
        13
    panda1001  
       2017-07-12 17:49:56 +08:00 via Android
    @zealot0630
    @enocher 指出的 syn 攻击就是利用三次握手机制 不知到是怎么防止 ddos ?
    andyL
        14
    andyL  
       2017-07-12 18:01:03 +08:00
    Mark
    andyL
        15
    andyL  
       2017-07-12 18:02:12 +08:00
    不该 mark 的,直接收藏了。

    期待前排大佬能把争论的地方讲具体、讲清晰一点
    anxious
        16
    anxious  
       2017-07-12 18:07:21 +08:00   ❤️ 3
    建立连接三次握手,常见的有一个 SYN 攻击。

    在三次握手的过程中,server 端会维护一个队列,这个队列中都是 已经向 client 返回 ACK,并等待 client ACK 的请求。

    如果 client 在此时恶意的不发送 ACK,而是不停的发送 SYN,
    就会导致 SERVER 端 的队列被占满,无法接受正常的 TCP 三次握手请求。
    qien
        17
    qien  
       2017-07-12 18:22:10 +08:00
    TIME_WAIT 状态是怎样产生的,为什么要这样做?
    xx998
        18
    xx998  
       2017-07-12 18:28:28 +08:00 via Android
    @anxious 多谢科普
    ivechan
        19
    ivechan  
       2017-07-12 18:37:17 +08:00
    为什么要把教科书搬到微信公众号上。。
    enocher
        20
    enocher  
    OP
       2017-07-12 18:51:46 +08:00
    @qien The client waits for a period of time equal to double the maximum segment life (MSL) time, <b>to ensure the ACK it sent was received.</b>
    jtsai
        21
    jtsai  
       2017-07-12 18:57:37 +08:00 via Android
    那什么是 tcp 流
    hsmocc
        22
    hsmocc  
       2017-07-12 19:14:36 +08:00 via iPhone
    感觉在握手时候应该强调下序列号同步的功能
    tempdban
        23
    tempdban  
       2017-07-12 19:37:39 +08:00 via Android
    看了评论舒了一口气
    另外楼主这算是翻车么
    cxbig
        24
    cxbig  
       2017-07-12 20:04:36 +08:00
    老实说,这些贴图质量实在是太土了。下面的 Wireshark 的部分跟本就看不清。
    做推广能不能有点诚意。
    JiPhone
        25
    JiPhone  
       2017-07-12 20:35:48 +08:00
    补充一个[wireshark 网络分析]( https://book.douban.com/subject/26268767/),考虑到了 tcp 四次挥手中的 sack 导致的 seq 不一致问题
    paradoxs
        26
    paradoxs  
       2017-07-12 20:37:33 +08:00
    好 我来提个问
    paradoxs
        27
    paradoxs  
       2017-07-12 20:37:58 +08:00
    不小心发出去了。 接上面
    HTTP 协议的无状态和 keep alive 的关系是什么
    ljy2010a
        28
    ljy2010a  
       2017-07-12 20:45:10 +08:00
    把时序图 和各个状态放出来吧
    netfee
        29
    netfee  
       2017-07-12 21:24:44 +08:00 via Android
    恩,看着关注了一大堆公众号,不过基本上不会去看。为什么对封闭的微信热情这么高,开放的 Web 不是更好!?感谢楼主科普
    ixinshang
        30
    ixinshang  
       2017-07-12 21:34:08 +08:00 via Android
    值得看 谢谢
    facetest
        31
    facetest  
       2017-07-12 21:37:48 +08:00 via Android
    @zealot0630 建议多看书。
    zoffy
        32
    zoffy  
       2017-07-12 22:03:44 +08:00
    作为一个 web 开发,平时都是用 http 协议,到底什么情况才需要深入到 tcp/ip 啊??
    CRVV
        33
    CRVV  
       2017-07-12 22:18:29 +08:00
    "TCP 三次握手和四次挥手不管是在开发还是面试中都是一个非常重要的知识点,它是我们优化 web 程序性能的基础"
    求问如何使用这些知识来优化 web 程序?
    CRVV
        34
    CRVV  
       2017-07-12 22:26:58 +08:00
    三次握手的作用、带来的问题、问题的解决方案、解决方案仍然存在的问题,全部都在
    https://tools.ietf.org/html/rfc7413 里面,讲得很清楚。而且 7413 比 793 短得多,很容易读完
    Antidictator
        35
    Antidictator  
       2017-07-13 08:09:35 +08:00 via Android
    @Geoion 我老师经常转,孩子都几个他
    realfreesky
        36
    realfreesky  
       2017-07-13 08:53:57 +08:00
    @qien 因为网络的不可靠性,在客户端发送了 ack 包之后,还需要等待 2ms 才到 closed 状态,因为 ack 包可能丢失,对方会重传 FIN 包,这时候客户端需要重传
    Mutoo
        37
    Mutoo  
       2017-07-13 10:43:00 +08:00
    @zealot0630 三次握手给 DDoS 提供了机会,并不是用来防 DDoS 的。
    tony1016
        38
    tony1016  
       2017-07-13 10:56:06 +08:00
    还是喜欢这个版本:

    你瞅啥
    瞅你咋滴
    呦,咋俩唠唠
    suixinqiejing
        39
    suixinqiejing  
       2017-07-13 17:36:05 +08:00
    萌新 请教。

    在第二次通信中,B 向 A 发送信息之后,A 可以确认自己的发信能力和 B 的收信能力没有问题,但是 B 不知道自己的发信能力到底如何,所以就需要第三次通信。

    B 向 A 发信息 为什么是确认 A 的发信能力。
    suixinqiejing
        40
    suixinqiejing  
       2017-07-13 17:56:38 +08:00
    上一个问题问的犹如智障 ,请无视。
    anxious
        41
    anxious  
       2017-07-13 21:45:13 +08:00   ❤️ 2
    @paradoxs 无状态和 keep-alive 其实没有关系,是从两个角度上描述的。

    无状态,意思是 HTTP 协议 的前后两次请求,是相互无关的,本次的 HTTP 请求,对上一次的 HTTP 请求没有影响,对下一次的请求没有影响。

    keep-alive 可以从 TCP 的长连接,还是短连接 来说。
    在 HTTP 早先的版本,默认是 一次 HTTP 请求、响应完成,就断开连接。这就是短连接。

    后续因为 server、client 的性能都更好,所以就希望能够长连接,来减少 TCP 建立连接的消耗,所以后面希望推动长连接。
    但为了兼容以前短连接的历史原因,如果需要长连接,请明确声明 Keep-alive。
    anxious
        42
    anxious  
       2017-07-13 21:51:53 +08:00
    @suixinqiejing 对于这个的理解,不能站在上帝视角来看,你应该单纯的站在 A 的角度来看。

    比如,你就是 A,你给 B 写信,你把信投入了邮筒之后,你怎么确定的知道你的信件送达到了 B ?
    就是 B 给你回信,而且内容 与 你寄出去的那一封是相关的。

    你这个时候,才能确认 你的信 之前确实到达了 B。
    ytlm
        43
    ytlm  
       2017-07-14 16:07:02 +08:00
    @qien http://vcpu.me/TIME_WAIT%E7%8A%B6%E6%80%81%E5%88%86%E6%9E%90/ 这个对 TIME_WAIT 解释的很好,可以看下
    ytlm
        44
    ytlm  
       2017-07-14 16:09:29 +08:00
    本质山应该是为了在不可靠的网络上建立可靠的传输通道,三次刚好是一个比较稳妥的
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2813 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 00:08 · PVG 08:08 · LAX 16:08 · JFK 19:08
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.