面试官又双叒叕问你TCP的三次握手和四次挥手?看这里!有图有真相!!

2021-02-23 19:53:51 1222
  • 本文旨在搞清楚tcp,其他相关衍生知识会捎带提一下,如果需要了解更多知识,请留言给我!

先来了解一下osi

  • 开放式系统互联模型(英语:Open System Interconnection Model,缩写:OSI;简称为OSI模型)是一种[概念模型],由[国际标准化组织]提出,一个试图使各种计算机在世界范围内互连为网络的标准框架。定义于ISO/IEC 7498-1。
  • 该模型将通信系统中的数据流划分为七个层,从跨通信介质传输位的物理实现到分布式应用程序数据的最高层表示。每个中间层为其上一层提供功能,其自身功能则由其下一层提供。功能的类别通过标准的通信协议在软件中实现。

每一层对应的设备和应用

  • 物理层:数据通信的基础设备,比如网卡(它提供了mac地址),网线,集线器,中继器,调制解调器
  • 数据链路层:管理相邻节点的数据通信!比如网桥,交换机
  • 网络层:路由器是工作在第三层的(在tcp/ip中属于第二层的,下面会讲到),决定数据在网络中的传输路径,常见的有:IP、ICMP、IPX、BGP、OSPF、RIP、IGRP、EIGRP、ARP、RARP、X.25
  • 传输层:管理端到端的通信连接,那什么是端到端?就是计算机以端口来标记不同的网络进程,而两个远程计算机的进程交互,就是端到端。常见的有:TCP、UDP、RTP、SCTP、SPX、ATP、IL
  • 会话层: 会话层(Session)是建立在传输层之上,利用传输层提供的服务,使应用建立和维持会话,常见的有:ASAP、ISO 8327 / CCITT X.225、RPC、NetBIOS、Winsock、BSD sockets、SOCKS、密码验证协议
  • 表示层: 数据处理,比如编码解码,加密解密等,常见的有:XDR、ASN.1、NCP、TLS、ASCII
  • 应用层: 为计算机用户提供接口和服务,是七层中和用户最近的一层,HTTP(万维网服务)、FTP(文件传输)、SMTP(电子邮件)、SSH(安全远程登录)、DNS(名称⇔IP地址寻找)以及许多其他协议。

TCP/IP四层模型

  • osi是理论专家提出来的,但是在实际应用中,发现并不实用,通常人们认为OSI模型的最上面三层(应用层、表示层和会话层)在TCP/IP组中是一个应用层。而物理层和数据链路层应该是属于网络接口层,于是就有了tcp/ip
image.png
  • 其实还有五层的,这里不做过多介绍

聊一聊TCP

  • TCP,全称Transmission Control Protocol,是一种传输控制协议,TCP协议也是计算机网络中非常复杂的一个协议
  • TCP的特点:
    • TCP是面向连接的协议
    • TCP是端到端的链接
    • TCP提供可靠的传输服务
    • TCP协议提供全双工的通信
    • TCP是面向字节流的协议
  • TCP报文格式

TCP报文首部

  • 源端口和目的端口,各占2个字节,分别写入源端口和目的端口;
  • 序号,占4个字节,TCP连接中传送的字节流中的每个字节都按顺序编号。例如,一段报文的序号字段值是 301 ,而携带的数据共有100字段,显然下一个报文段(如果还有的话)的数据序号应该从401开始;
  • 确认号,占4个字节,是期望收到对方下一个报文的第一个数据字节的序号。例如,B收到了A发送过来的报文,其序列号字段是501,而数据长度是200字节,这表明B正确的收到了A发送的到序号700为止的数据。因此,B期望收到A的下一个数据序号是701,于是B在发送给A的确认报文段中把确认号置为701;
  • 数据偏移,占4位,它指出TCP报文的数据距离TCP报文段的起始处有多远;
  • 保留,占6位,保留今后使用,但目前应都位0;
  • 紧急URG,当URG=1,表明紧急指针字段有效。告诉系统此报文段中有紧急数据;
  • 确认ACK,仅当ACK=1时,确认号字段才有效。TCP规定,在连接建立后所有报文的传输都必须把ACK置1;
  • 推送PSH,当两个应用进程进行交互式通信时,有时在一端的应用进程希望在键入一个命令后立即就能收到对方的响应,这时候就将PSH=1;
  • 复位RST,当RST=1,表明TCP连接中出现严重差错,必须释放连接,然后再重新建立连接;
  • 同步SYN,在连接建立时用来同步序号。当SYN=1,ACK=0,表明是连接请求报文,若同意连接,则响应报文中应该使SYN=1,ACK=1;
  • 终止FIN,用来释放连接。当FIN=1,表明此报文的发送方的数据已经发送完毕,并且要求释放;
  • 窗口,占2字节,指的是通知接收方,发送本报文你需要有多大的空间来接受;
  • 检验和,占2字节,校验首部和数据这两部分;
  • 紧急指针,占2字节,指出本报文段中的紧急数据的字节数;
  • 选项,长度可变,定义一些其他的可选的参数。

面试官又双叒叕问你TCP的三次握手和四次挥手?来,答案在这里!

  • 先来通俗的讲一讲,什么是三次握手,其实三次握手的目的在于一句话,就是让我知道你已经知道了,比如下面一个打电话的场景; 刘备打电话给张飞
    • 如果两个人想要有一个正常的通话,必须保证张飞能听得到, 于是有了第一次握手,刘备问张飞,你能听得到吗?

    • 张飞听到刘备的请求,开始第二次握手,说,我能听到,你呢?

    • 刘备听到了张飞的话,首先自己知道了,原来张飞那小子能听到我说话,于是建立了连接,但是张飞那傻小子还等着刘备回信呢,在那犯嘀咕,我大哥到底能不能听到我说话,这个时候刘备开始了第三次握手,告诉张飞,我也可以听到你说话。张飞听到后,也建立了连接,至此,连接完成!

    • 然后两人就开始得啵得啵得!

那么我们从专业的角度解读一下这个三次握手

  • 第一次握手,发送方主动发起请求,SYN=1 表示我要建立连接,seq=x 表示序列号(用于甄别是哪一次的请求,序列号即被消耗掉了)

  • 第二次握手,接收方接成功收到请求后,先是ACK=1 表示接收到了,SYN=1表示我也要建立连接,seq=y 表示序列号(用于甄别是哪一次的请求,序列号即被消耗掉了),ack=x+1,表示我想要你的序列号是 x+1;

  • 第三次握手,发送方 ACK=1,表示我接收到了,seq=x+1 这是接收方要求要的,ack=y+1 表示下一次想要的序列号

  • 其中第二次握手之后,发送方就已经建立了连接,第三次握手之后,接收方建立连接;

下面我使用wireshark 抓包工具来看一下三次握手的过程

  • 第一次握手
image.png
  • 这就是我们前面提到的tcp报文结构

  • 再来看一下tcp标记

  • 第二次握手

第三次握手

  • 这里面强调一个问题

为什么要发送第三个确认报文?其实主要还是为了给这次握手做个了结,如果没有第三次会发生什么情况呢? 弄清这个问题,我们需要先弄明白三次握手的目的是什么,能不能只用两次握手来达到同样的目的。

第一次握手:客户端发送网络包,服务端收到了。 这样服务端就能得出结论:客户端的发送能力、服务端的接收能力是正常的。 第二次握手:服务端发包,客户端收到了。 这样客户端就能得出结论:服务端的接收、发送能力,客户端的接收、发送能力是正常的。不过此时服务器并不能确认客户端的接收能力是否正常。 第三次握手:客户端发包,服务端收到了。 这样服务端就能得出结论:客户端的接收、发送能力正常,服务器自己的发送、接收能力也正常。 因此,需要三次握手才能确认双方的接收与发送能力是否正常。

试想如果是用两次握手,则会出现下面这种情况:

如客户端发出连接请求,但因连接请求报文丢失而未收到确认,于是客户端再重传一次连接请求。后来收到了确认,建立了连接。数据传输完毕后,就释放了连接,客户端共发出了两个连接请求报文段,其中第一个丢失,第二个到达了服务端,但是第一个丢失的报文段只是在某些网络结点长时间滞留了,延误到连接释放以后的某个时间才到达服务端,此时服务端误认为客户端又发出一次新的连接请求,于是就向客户端发出确认报文段,同意建立连接,不采用三次握手,只要服务端发出确认,就建立新的连接了,此时客户端忽略服务端发来的确认,也不发送数据,则服务端一致等待客户端发送数据,浪费资源。

还是刚才打电话的栗子,如果是两次握手,第一次刘备说,你能听得到吗?但是是张飞没听到,可能是某一个瞬间 信号不好,网络阻塞,或者被外星人劫持,由于刘备没有收到张飞的回应,又发了一次请求,说,小飞飞,你听得到吗?这时张飞听到了,开始第二次握手,回答说我听到了,此时连接建立!通话结束后,张飞刚想走,这个时候听到大哥第一次的呼唤,你听得到吗吗吗吗????于是张飞又一次建立了连接,而此时,刘备已经去白帝城了,而张飞一直在等,等他的大哥。。。。。很悲剧的故事,对不对,哈哈,但是对于计算机来说,这是一种资源浪费!

再来看看四次挥手,即TCP连接的释放

先来通俗的,简单易懂的讲一下;比如下面这个场景

  • 下课铃响,莫小贝对老夫子说,夫子,下课了,这是第一次挥手,莫小贝就不再跟老夫子互动了,坐等下课(等待),夫子也不看莫小贝的反应了(关闭等待),

  • 但是夫子爱拖课(大家最烦这种套路的老师啦,哈哈)!说,我知道了,等我讲完这一点就下课,于是莫小贝还得干等(第二次等待),这是第二次挥手,

  • 老夫子孤独的讲了五分钟后,说我讲完了,下课!这是第三次挥手(最后确认)

  • 莫小贝说,我知道了,你大爷的(有点不尊师重道哈,要批判)!这是第四次挥手

  • 至此,四次挥手完毕,tcp释放连接

  • 我们再从专业的角度解读一下

  • 第一次挥手,发送方主动发起释放请求,FIN=1表示结束连接,seq=u和前面一样序列号

  • 第二次挥手,接收方ACK=1表示接收方收到了,seq=v是 接收方的序列号,ack=u+1,表示下次希望接收的序列号

  • 第三次挥手,接收方发起释放请求,FIN=1表示要释放,ACK=1表示接收到了释放请求,seq=w表示本次序列号,ack=u+1表示下次希望接收的序列号

  • 第四次挥手,发送方ACK=1表示接收到了,seq=u+1,是第三次挥手要求的序列号,ack=w+1表示希望下次得到的序列号;

  • 从上面可以看出,发送方发送断开请求后,接收方就关闭了等待,由于发送方没有接收到接收方的断开请求,就一直处于等待状态,只到第三次挥手,开始等待计时!而接收方在第四次挥手后就关闭了。发送方在等待计时结束后关闭

  • 下面我们来说一说什么是 等待计时器

    • 先了解一下这个,MSL(Max Segment Lifetime): 最长报文段寿命,就是说报文的最长存活时间,怎么设置呢?以linux为例,cat /proc/sys/net/ipv4/tcp_fin_timeout,好了,这个点到为止!
    • tcp的等待计时 时长一般是 2MSL,就是两倍的报文寿命
  • 为什么要等待2MSL? 1.为了保证所有的报文都已经传送(或者过期) 2.为了保证发送方的ACK可以到达接收方,在2MSL时间内如果接收方没有收到发送方的ACK,则接收方会再次发起第三次挥手

来看一下四次挥手的抓包

  • 第一次挥手

  • 第二次挥手

  • 第三次挥手

  • 第四次挥手

如果觉得本文不错,给予一点点支持吧。

image.png
image.png