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

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. 【转】nvidia-smi 命令解读

    nvidia-smi是linux下用来查看GPU使用情况的命令.具体的参数信息详见 原文:http://blog.csdn.net/sallyxyl1993/article/details/62220 ...

  2. js——正则表达式

    1. 创建一个正则表达式 var patt=new RegExp(pattern,modifiers);var patt=/pattern/modifiers; var index = str.sea ...

  3. Confluence 6 中进行用户管理的优化配置和限制的基本建议

    避免跨目录的多个用户名:如果你连接了超过一个的目录服务器,我们建议你需要确定你的用户名在目录服务器中是唯一的.例如:我们不建议你定义一个用户同时在'Directory1' 和 'Directory2' ...

  4. C#概念总结(三)

    1.定义结构体 定义了结构体,必须使用了stuct语句,struct定义了一个带有多个成员的的新数据类型.C# 的结构不同于C的.具有一下等特点: 结构可以有方法.字段.索引.属性.运算方法和事件.结 ...

  5. XSS-HTML&javaSkcript&CSS&jQuery&ajax

    1.设置不同的样式列表 <style> ul.a{list-style-tyrp:circle;}    ul.b{list-style-type:square;}   ul.c{list ...

  6. arm指令1

    .section .text.writeFUNCTION(write) ldr r12, =__NR_write swi #0 bx lr LDR: LDR 的两种用法 1)LDR pc, =MyHa ...

  7. ftp的自动部署以及添加虚拟账户的脚本

    #!/bin/bash #本脚本为自动化安装vsftp,使用虚拟用户认证登录ftp上传下载文件 echo =============================================== ...

  8. Python函数之递归函数

    递归函数的定义:在这个函数里再调用这个函数本身 最大递归深度默认是997或者998,python从内存角度做的限制 优点:代码变简单 缺点:占内存 一:推导年龄 问a的值是多少: a 比 b 小2,b ...

  9. java数据

    因为曾经干了啥事儿,才印象特别深刻. 将byte存入String的后果 String res = ""; res += (char) 0xc3; byte[] bytes = re ...

  10. ffmpeg切割视频

    using System.Diagnostics; public static void carveVideo() { var inputpath = @"d:\1.mp4"; v ...