为什么三次握手,而不是两次或者四次五次?

2019/3/4更新:

      在阅读了很多技术博客后,发先大家对为什么三次握手不是两次众说纷纭;我觉得说的最好的是英文文章对TCP的解读。TCP和UDP的区别就是可靠与不可靠传输。

    为了实现可靠数据传输, TCP 协议的通信双方, 都必须维护各自的一个序列号, 以标识发送出去的数据包中, 哪些是已经被对方收到的。 三次握手的过程即是通信双方相互告知序列号起始值, 并确认对方已经收到了序列号起始值的必经步骤。

在这过程中序号seq和确认号ack使用是核心。(详情请看下文)
如果只是两次握手, 至多只有连接发起方的起始序列号能被确认, 另一方选择的序列号则得不到确认。

补充:

  第一次握手:A传给B包丢了的话,A会周期性重传,直到收到B的确认。

  第二次握手:B回传给A的序号+确认号包,A没有收到,B会周期性重传,直到收到A的确认。

    第三次握手:A发给B的包丢失

        A发完包后,单方面认为TCP是连接成功了,但是B只认为TCP是活跃状态。

情况1:假设双方没有数据要发送,B会重传,知道再收到A的确认。收到之后AB确认连接成功。

        情况2:A有数据发送,B收到A的数据和确认包,会认为TCP连接成功。并接收A数据。


往期:

首先要了解三次握手的具体过程:

为了建立客户端和服务端的数据连接进行TCP的三次交互

 

(1)第一次握手:建立连接时,client端发送给server端一个SYN包(标识位SYN=1和client的初始序列号seq=x,此时标识位ACK确认号=0,表示这是一个TCP连接请求数据报文),并进入SYN_SENT状态,等待server端确认。

(2)第二次握手:server端收到c端的发来的SYN包(即收到c端发来的连接请求),同时自己也发送一个SYN+ACK包(标识位SYN和ACK都置1,表示这是确认报文。server.seq=y,以及server对client初始序号的确认号server.ack=client.seq+1=x+1)。

(3)第三次握手:client收到server的SYN+ACK包,并向server发送一个序列号(client.seq=x+1),确认号为ack(client.ack=server.seq+1=y+1),此包发送完毕,客户端和服务器进入ESTAB_LISHED(TCP连接成功)状态,完成三次握手。

为什么是三次:如果只有两次(也就是客户端发送—服务端收到并发送—客户端收到)这个过程。假如服务端发出来的数据客户端没有收到呢(数据丢失的情况)? 客户端等待一段时间后,会重新建立连接,即重新发送连接请求。如果这个过程重复很多次,那么就会产生非常多的无效连接,占用大量资源,甚至导致服务器崩溃(也就是“SYN洪水攻击”现象)。

第三次握手,就是为了防止 因数据丢失或者数据传输延迟,导致客户端重启连接的现象。这也就防止了因服务器收到过的无效链接而占用大量资源。

为什么不是四次或五次?  对于TCP连接过程即C—>S—>C;如果是四次握手那么会产生和两次握手同样的无效化连接现象,而且比两次握手更浪费时间的资源。 那么你也就知道了为什么不五次握手,三次五次七次都可以做到确认并连接成功,为什么不用最少的时间和资源呢?

为什么四次挥手?

 

第一次挥手:首先,client端发送一个FIN (用来释放一个连接。FIN=1表示:此报文段的发送方的数据已经发送完毕,并要求释放运输连接),用来关闭client端到server的数据传送,然后等待server端的确认。其中终止标志位FIN=1,序列号seq=u。

第二次挥手:当server收到这个FIN后,它会发送一个ACK,确认号ack(ack=client.seq+1=u+1),序列号seq=v,确认已经收到了client端的终止请求。

第三次挥手:关闭服务器到客户端的连接,发送一个FIN给客户端,FIN=1,更新的序列号seq=w,确认号ack=u+1(和第二次挥手相同)。

第四次挥手:当client收到FIN后,并发回一个ACK报文确认已经收到,其中seq=u+1,ack=server.seq+1。首先进行关闭的一方将执行主动关闭,而另一方执行被动关闭。

总结全过程:客户端第一次发送FIN后,进入终止等待状态,服务器收到客户端连接释放报文段后,就立即给客户端发送确认,服务器就进入CLOSE_WAIT状态,此时TCP服务器进程就通知高层应用进程,因而从客户端到服务器的连接就释放了。此时是“半关闭状态”,即客户端不可以发送给服务器,服务器可以发送给客户端。此时,如果服务器没有数据报发送给客户端,其应用程序就通知TCP释放连接,然后发送给客户端连接释放数据报,并等待确认。客户端发送确认后,进入TIME_WAIT状态,但是此时TCP连接还没有释放,然后经过等待计时器设置的2MSL后,才进入到CLOSED状态。

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

答:因为当Server端收到Client端的SYN连接请求报文后,可以直接发送SYN+ACK报文。其中ACK报文是用来应答的,SYN报文是用来同步的。但是关闭连接时,当Server端收到FIN报文时,很可能并不会立即关闭SOCKET,所以只能先回复一个ACK报文,告诉Client端,"你发的FIN报文我收到了"。只有等到我Server端所有的报文都发送完了,我才能发送FIN报文,因此不能一起发送。故需要四步握手。(原文:https://blog.csdn.net/qq_38950316/article/details/81087809)

为什么最后会有客户端等待2MSL时间?

MSL是最大报文生存时间。为了保证客户端发送的最后一个ACK报文段能够到达服务器。即最后一个确认报文可能丢失,服务器会超时重传,然后服务器发送FIN请求关闭连接,客户端发送ACK确认。一个来回是两个报文生命周期。

如果没有等待时间,发送完确认报文段就立即释放连接的话,服务器就无法重传,因此也就收不到确认,就无法按步骤进入CLOSED状态。

并且可以防止已经失效的连接请求报文出现在连接中。经过2MSL,在这个连续持续的时间内,产生的所有报文段就可以都从网络消失。

总结TCP为什么三次握手四次挥手的更多相关文章

  1. 在深谈TCP/IP三步握手&四步挥手原理及衍生问题—长文解剖IP

    如果对网络工程基础不牢,建议通读<细说OSI七层协议模型及OSI参考模型中的数据封装过程?> 下面就是TCP/IP(Transmission Control Protoco/Interne ...

  2. [na]TCP的三次握手四次挥手/SYN泛洪

    1.TCP报文格式 上图中有几个字段需要重点介绍下: (1)序号:Seq序号,占32位,用来标识从TCP源端向目的端发送的字节流,发起方发送数据时对此进行标记. (2)确认序号:Ack序号,占32位, ...

  3. TCP/IP三次握手四次挥手

    本文通过图来梳理TCP-IP协议相关知识.TCP通信过程包括三个步骤:建立TCP连接通道,传输数据,断开TCP连接通道.如图所示,给出了TCP通信过程的示意图. TCP 三次握手四次挥手 主要包括三部 ...

  4. TCP协议—三次握手四次挥手的原理<转>

    三次握手四次挥手的原理   TCP是面向连接的,无论哪一方向另一方发送数据之前,都必须先在双方之间建立一条连接.在TCP/IP协议中,TCP 协议提供可靠的连接服务,连接是通过三次握手进行初始化的.三 ...

  5. 救救孩子吧,到现在还搞不懂TCP的三次握手四次挥手

    本文在个人技术博客同步发布,详情可用力戳 亦可扫描屏幕右侧二维码关注个人公众号,公众号内有个人联系方式,等你来撩...   前几天发了一个朋友圈,发现暗恋已久的女生给我点了个赞,于是我当晚辗转反侧.彻 ...

  6. 通俗了解TCP/IP三次握手四次挥手

    前言: tcp/ip通信机制是计算机中很重要的一个知识点,不是一句两句就能解释清楚的,需要反复推敲其中的玄妙. 通俗理解: 但是为什么一定要进行三次握手来保证连接是双工的呢,一次不行么?两次不行么?我 ...

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

    一.TCP概述 每一条TCP连接都有两个端点,这种端点我们叫作套接字(socket),它的定义为端口号拼接到IP地址即构成了套接字, 例如,若IP地址为192.0.0.1 而端口号为8000,那么得到 ...

  8. 详解 TCP的三次握手四次挥手

    本文转载来自https://blog.csdn.net/qzcsu/article/details/72861891 背景描述 通过上一篇中网络模型中的IP层的介绍,我们知道网络层,可以实现两个主机之 ...

  9. TCP/IP 三次握手-四次挥手

    TCP的建立需要三次握手,断开需要四次挥手. 首先三次握手: 首先,客户机向服务器发送请求报文,服务器回复ACK,并分配资源,而客户端接受到ACK后回复确认报文,并分配资源,此时三次握手完成. 四次挥 ...

  10. TCP的三次握手四次挥手

    一.三次握手 1.wireshark 抓包 2.TCP报文手部 注意标志位: 1).同步 SYN = 1 表示这是一个连接请求或连接接受报文. 2).只有当 ACK = 1 时确认号字段才有效.当 A ...

随机推荐

  1. linux命令知识点

    1. 例二:列出当前目录中所有以“t”开头的目录的详细内容,可以使用如下命令: 命令:ls -l t* 例六:计算当前目录下的文件数和目录数 命令: ls -l * |grep "^-&qu ...

  2. Modbus库开发笔记之十:利用协议栈开发Mosbus RTU Slave应用

    上一节我们使用协议占开发了一个Modbus TCP Server应用.接下来我们使用协议栈在开发一个基于串行链路的Mosbus RTU Slave应用. 根据前面对协议栈的封装,我们需要引用Modbu ...

  3. Confluence 6 的系统配置信息的示例

    awt.toolkit sun.awt.X11.XToolkit file.encoding.pkg sun.io java.specification.version 1.8 sun.cpu.isa ...

  4. Confluence 6 用自带的用户管理

    在一些特定的情况下,你可能希望禁用 Confluence 自带的用户管理或完全使用外部的用户目录进行用户管理.例如 Jira 软件或者 Jira Service Desk.你可以在 Confluenc ...

  5. Swift 新增fileprivate 详解

    以前项目中只要用了private  那么在同一个文件同一个类中还是能访问的(比如一个类中写了一个extension) swift3.0现在不行了 新增了一个fileprivate 的访问控制 以前的p ...

  6. Django框架第一篇基础

    一个小问题: 什么是根目录:就是没有路径,只有域名..url(r'^$') 补充一张关于wsgiref模块的图片 一.MTV模型 Django的MTV分别代表: Model(模型):和数据库相关的,负 ...

  7. python网络爬虫笔记(八)

    一.pthon 序列化json格式 1.将python内置对象转换成json 模块,dumps()方法返回的是一个str,内容是标准的JSON,dump()方法可以直接吧JSON写入一个file-li ...

  8. Allegro PCB Design GXL (legacy) 刷新PCB封装(Package)中的焊盘(Padstack)

    Allegro PCB Design GXL (legacy) version 16.6-2015 “人有失足,马有失蹄”. 像这个电位器的封装的Pin 6,在制作Padstack时,因没有添加SOL ...

  9. CentOS安装jdk的三种方法

    方法一:手动解压JDK的压缩包,然后设置环境变量 方法二:用yum安装JDK,(全称为 Yellow dog Updater, Modified)是一个在Fedora和RedHat以及CentOS中的 ...

  10. IDEA部署项目和多余的项目删掉的演示