PS:通俗一点的解释都会在引用块中

Nothing is true, Everything is permitted.

0. 什么是TCP

TCP,全称Transmission Control Protocol,是一种面向连接、可靠的、基于字节流的单播协议。与我们常说的TCP/IP协议不同,TCP/IP是一个协议族,涉及到OSI模型中的网络层、应用层和应用层。而我们要聊的TCP就是在传输层的协议,现在应用的特别广泛的HTTP请求,就是基于TCP的。

1. 三次握手

所谓面向连接很好理解,就像我们要对远程服务器发出一个指令,首先我们需要登录上去。这个登录就是一个连接的过程。

在做数据交换之前,通信双方必须在彼此建立一条连接。也就是通信双方都维护了一份对方的信息,比如IP地址和端口号。说到建立连接,就不得不提到经典的三次握手和四次挥手。

1.1 为什么不两次握手

三次握手让通信双方都明确有一个连接正在建立,也为了确保客户端和服务器同时具有发送接收的能力。而两次握手做不到这一点。我们现在从另外一个角度来看一下三次握手,那就是为什么要三次握手?我两次握手它不香吗?让我们用一段对话来模拟如果真的采用两次握手,会带来什么问题。

朋友:喂,喂?听得到吗

你:听得到…你声音能不能小点

这就是两次握手。

按照人的逻辑来说,这已经是一次正常的对话了是吧,下一步难道不是建立连接吗?说下一步之前,需要先了解做三次握手的目的是什么。三次握手让通信双方都明确有一个连接正在建立,也为了确保客户端和服务器同时具有发送接收的能力。

我们来分析一下上面的那段对话。

朋友问你能不能听到,说明朋友具有发送能力;你听到了朋友的问题,说明你具有接收能力

如果只有两次握手,问题在哪儿呢?

站在朋友的角度,他知道你同时具有发送接收能力

但站在你(服务器)的角度,你只知道朋友具有发送能力,因为你不知道你发的声音能不能小点,他到底有没有收到

服务器不清楚客户端是否有接收能力的情况下,就算数据包真的发出去了,但无法知道客户端是否收到了数据。这样的就是不可靠的连接了。

而且,真实的网络传输中,出现网络延迟是常有的事,如果客户端发送了请求建立连接的数据包,由于网络延迟,数据包没有到达,客户端又发了一次,服务器收到之后建立了连接。

但是当前的连接关闭后,由于网络延迟的没有到达的包到了服务器,服务器又建立了连接,但是此时客户端已经断开了,这样就白白浪费了服务器的资源。

如果觉得上面的例子还是不能让你理解, 为什么两次握手不行。请看下面这个终极例子。

朋友:快借我点钱,XX宝账号123XXXXXXXX

你:好的, 你的帐号是123XXXXXXXX吗

。。。。。。(无应答)

你的内心:??????

如果你是被借钱的那个,你敢把钱转过去吗?


0341fda0555dc92b70a2ea4874115d5b

简单总结一下两次握手所带来的问题:不可靠,还会造成网络资源的浪费。

1.2 三次握手的过程

上面我们讨论了为什么要三次握手,接下来我们用几个专业术语来解释一下三次握手的过程。

  • 服务器开始监听某个端口,此时服务器进入了LISTEN状态

  • 客户端最初是CLOSED状态,然后向服务器发送一个SYN标志位的数据包,主动发起连接。客户端变成SYN-SENT状态

  • 服务器接收到客户端的SYN数据包,通过标志位知道了客户端想要建立连接。于是回了客户端一个SYN和ACK,表示收到了请求。服务器的自身状态变为了SYN-RCVD

  • 客户端收到了服务器的ACK,表示服务器知道了客户端想要建立连接。然后客户端再给服务器回了一个ACK表示自己收到了(或者说能够收到)服务器的消息,发送完这个ACK后,客户端的状态变成了ESTABLISH

  • 服务器收到了客户端的ACK,服务器的状态也变成ESTABLISH


2. 四次挥手

2.1 模拟四次挥手

老规矩,还是让我们用一段对话来模拟TCP的四次挥手。

场景,你跟你的朋友们正在外面high

你:你们继续玩,我就先走了,明天还要上班(第一次)

老铁:(老铁看到你在跟他说话且从你说的话中知道你要走了,老铁也用肢体语言告诉你他知道你要走了)(第二次)

老铁:那好吧, 路上注意安全哈 (第三次)

你:好的,下次再约 (第四次)

这就是通俗版本的四次挥手的解释,下面从专业的角度来看看。

2.2 四次挥手的过程

我们来看一下完整的流程。

  • 最初,客户端和服务器都处于ESTABLISH状态

  • 客户端想要断开连接,便主动向服务器发送标志位为FIN的数据包。发送之后客户端的状态变为FIN-WAIT-1,同时客户端也变成了半关闭状态,即无法向服务器发送数据包了,只能接收来自服务器的数据

  • 服务器收到客户端的FIN数据包,状态变为CLOSE-WAIT,并回给客户端一个表示确认的数据包ACK

  • 客户端收到了ACK之后,状态变为FIN-WAIT-2

  • 然后,服务器向客户端发送FIN数据包,服务器状态变为LAST-ACK

  • 客户端收到FIN数据包,客户端状态变为TIME-WAIT。然后回一个确认数据包ACK给服务器

  • 然后客户端等待2MSL,如果在这段时间内,没有收到服务器重发的消息,说明服务器收到了ACK

  • 四次挥手到此结束,连接断开



我们再来模拟一次刚刚的场景。

场景,你跟你的朋友们正在外面high

你:你们继续玩,我就先走了,明天还要上班(第一次)

老铁:(老铁喝high了,反射弧无限延长)

你肯定得再说一次啊,给朋友说你要走了,于是你又说了一次。

你:你们继续玩,我就先走了,明天还要上班(第一次)

老铁:(老铁喝high了,反射弧无限延长)

。。。。。。

如此反复

实际情况是,如果是两次挥手,也就是把服务器给客户端的ACK和FIN合并为同一个,如果此时网络出现了延迟,站在客户端的角度来看,客户端会认为刚刚发送的FIN报文并没有到达服务器,于是会在再重新发送一次。如果延迟的时间较长,那么客户端将会一直重新发送FIN的TCP报文。

2.3 对比分析

结合抽象和具体的四次挥手,其实就很好理解了,我们用一个表格来总结一下。

描述状态 实际情况
你和你的朋友在外面high 客户端和服务器建立了连接
你和朋友说你要走了 客户端主动向服务器发送FIN,客户端状态变为FIN-WAIT-1
你的朋友听到了并理解了你要说的话,并通过肢体语言反馈给你他知道了 服务器收到FIN数据包,并回了一个ACK,服务器的状态变为CLOSE-WAIT。客户端收到ACK之后变为FIN-WAIT-2
你的朋友说“那好吧, 路上注意安全哈” 服务器向客户端发送FIN包,服务器变为LAST-CHECK。
你说“好的,下次再约” 客户端收到FIN包后状态变为TIME-WAIT。并回一个ACK给服务器。
你迟疑了一下,你的朋友并没有挽留你 客户端等待2MSL,如果没有收到服务器的重发消息,则说明服务器收到了ACK。
你离开了和朋友的聚会 四次挥手结束,连接断开

2.4 为什么要等待

MSL,即Maximun Segment LifeTime,报文最大生存时间。为什么在TIME-WAIT之后还需要等待2MSL呢?主要是两个原因,让我们结合例子来理解一下。

保证服务器收到ACK

假设你说了“好的,下次再约”。由于大家都在high,声音太大了。导致你的朋友没有听到你说的“好的,下次再约”这句话,然后你转头就走了。

如果你站在你朋友的角度,肯定会心里很不爽,好心提醒你,连句道别的话都没有?

这种情况就是服务器并没有收到客户端收到的ACK,站在服务器的角度,服务器并不知道客户端收到了自己发的FIN包。也就不会断开连接,但是客户端已经单方面的断开连接了。又造成了服务器的资源浪费,服务器也无法进入正常的关闭连接状态。

防止失效的数据包

同样,你说了”好的, 下次再约“后,你没有确认你的朋友是否听到了,扭头就走。你的朋友也喝多了,此时心里很不爽,骂了一句傻X。

这句话刚好被路过、站到了你刚刚站的位置上的哥们接住了,以为在说他,心里就很不爽,提着拳头就把你的朋友揍了一顿。

这种情况是指,客户端没有等待2MSL就直接断开,但是服务器此时仍然有些数据包需要发送,或者已经发了出去。但是数据包到了后,此时的端口已经被新的连接占用了,老的TCP报文就会与新连接的TCP报文冲突、混淆。

3. 结尾

后面如果我有时间,会继续尝试把枯燥的理论抽象成生活中一些简单的现象并且与专业的知识结合起来的文章风格,来帮助那些看理论知识很吃力的人。其实只要理解了整个思路,是不需要去死记硬背的。

如果文章中有不对的地方,还望各位大佬不吝赐教。

如果你觉得这篇文章对你有帮助,还麻烦点个赞关个注分个享留个言

也可以微信搜索公众号【SH的全栈笔记】,当然也可以直接扫描二维码关注


拜了个拜

【俗话说】换个角度理解TCP的三次握手和四次挥手的更多相关文章

  1. 你应该这么理解TCP的三次握手和四次挥手

    前言: TCP协议是计算机的基础,他本身是一个非常非常复杂的协议. 本文只是蜻蜓点水,将从网络基础以及TCP的相关概念介绍开始,之后再将三次握手,四次挥手这些内容来阐述. 最后介绍一些常见问题,并给出 ...

  2. 理解 TCP/IP 三次握手与四次挥手

    TCP建立连接为什么是三次握手,而不是两次或四次? TCP,名为传输控制协议,是一种可靠的传输层协议,IP协议号为6. 顺便说一句,原则上任何数据传输都无法确保绝对可靠,三次握手只是确保可靠的基本需要 ...

  3. 理解TCP/IP三次握手与四次挥手的正确姿势

    背景 注:以下情节纯属虚构,我并没有女朋友==. 和女朋友异地恋一年多,为了保持感情我提议每天晚上视频聊天一次. 从好上开始,到现在,一年多也算坚持下来了. 问题 有时候聊天的过程中,我的网络或者她的 ...

  4. TCP/IP三次握手与四次挥手的正确姿势

    0.史上最容易理解的:TCP三次握手,四次挥手 https://cloud.tencent.com/developer/news/257281 A 理解TCP/IP三次握手与四次挥手的正确姿势http ...

  5. TCP的三次握手与四次挥手理解及面试题

    TCP的三次握手与四次挥手理解及面试题(很全面) 转载自:https://blog.csdn.net/qq_38950316/article/details/81087809 本文经过借鉴书籍资料.他 ...

  6. TCP的三次握手与四次挥手详解

    TCP的三次握手与四次挥手是TCP创建连接和关闭连接的核心流程,我们就从一个TCP结构图开始探究中的奥秘  序列号seq:占4个字节,用来标记数据段的顺序,TCP把连接中发送的所有数据字节都编上一个序 ...

  7. 【图解】给面试官解释TCP的三次握手与四次挥手-Web运用原理及网络基础

    作者 | Jeskson 来源 | 达达前端小酒馆 轻松了解HTTP协议 为什么要学习网络协议呢?为什么要学习计算机完了呢?显然这很重要,至少能够帮助你找到工作的原因之一,学习网络知识点太多太多,没有 ...

  8. TCP 的三次握手和四次挥手

    参考资料: 1.TCP的三次握手与四次挥手理解及面试题: 2.Http协议三次握手和四次挥手: 3.TCP通信的三次握手和四次撒手的详细流程(顿悟) 前置: 序号(也称序列号) - Sequence ...

  9. TCP的三次握手与四次挥手

    TCP的三次握手与四次挥手 一.TCP(Transmission Control Protocol 传输控制协议) TCP是面向对连接,可靠的进程到进程通信的协议 TCP是提供全双工服务,即数据可在同 ...

随机推荐

  1. Angular(一)

    Angular开发者指南(一)入门介绍   什么是AngularAngularJS是动态Web应用程序的结构框架. 它允许您使用HTML作为模板语言,并允许您扩展HTML的语法以清晰,简洁地表达应用程 ...

  2. Matlab高级教程_第二篇:关于MATLAB转C#过程中MWArray到C#数组,C#数组到MWArray相互转换

    Matlab传递数据时使用的方法,那么Matlab计算完成后在C#中应该怎么获取它的计算数据呢? 需要遵循两个基本步骤: 弄清楚Matlab函数传回的数据到底是什么格式?struct?cell?cha ...

  3. 类似postman插件

    Talend API Tester - Free Edition https://chrome.google.com/webstore/detail/talend-api-tester-free-ed ...

  4. Tukey法

    Tukey法 在介绍Tukey方法前,首先了解学生化极差分布. 在概率论和统计学中,学生化极差分布是极差的抽样分布.该分布是一种连续型概率分布,用于在样本量较小且总体标准差未知的情况下估计正态分布总体 ...

  5. vue实现动态绑定class--(三目运算符)根据span数字内容改变其样式

    一.根据span数字内容改变数字本身样式(两种样式) <template> //使用三目运算符,判断当span的val是否小于0给其不同的class名 <span class=&qu ...

  6. signal之——异步回收机制

    前言:回收子进程之前用了wait()和非阻塞模型,今天学了信号以后可以使回收机制更上一层楼,通过信号函数,父进程只需要做自己的事情,接收到信号后就触发信号函数. 信号处理函数可能会出现的bug: 1. ...

  7. 洛谷-P3369-普通平衡树(Treap)

    题目传送门 标题说平衡树,那么应该AVL,红黑树都能过,但是这次做这题主要是学习Treap,所以花了几天搞出了这题.其他方法以后再说吧 Treap(带旋转) #include <bits/std ...

  8. 【UML】

    静态:类图,包图,部署图,构件图,对象图 行为:用例图,活动图,顺序图,状态图,交互图 [类图] http://www.uml.org.cn/oobject/201104212.asp [对象图] h ...

  9. python项目中对mysql数据库进行配置,并进行连接测试

    在settings.py中配置mysql数据库进行相关配置 DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME ...

  10. libphp5.so可能遇到的问题(转摘)

    libphp5.so可能遇到的问题(转摘) 安装完APACHE和PHP5后,经常在启动APACHE载入libphp5.so时发现问题.我把遇到的问题统计下来: 1.undefined symbol:S ...