远程通信协议学习(一)之网络协议

一个 http 请求的整个流程

在分布式架构中,有一个很重要的环节,就是分布式网络中的计算机节点彼此之间需要通信。所以通过一个 http 请求的整个流程来进行通信的知识的学习

常用名词解释

DNS (负责域名解析服务)

首先,用户访问一个域名,会经过 DNS 解析(Domain Name System),它和 HTTP 协议一样是位于应用层的协议,主要提供域名到 IP 的解析服务。我们其实不用域名也可以访问目标主机的服务,但是 IP 本身不是那么容易记,所以使用域名进行替换使得用户更容易记住。
在这里插入图片描述

CDN(加速静态内容访问速度)

在很多大型网站,会引入 CDN 来加速静态内容的访问, 这里简单给大家解释一下什么是 CDN**(Content Delivery Network)**,表示的是内容分发网络。CDN 其实就是一种网络缓存技术,能够把一些相对稳定的资源放到距离最终用户较近的地方,一方面可以节省整个广域网的带宽消耗,另外一方面可以提升用户的访问速度,改进用户体验。我们一般会把静态的文件(图片、脚本、静态页面)放到 CDN 中。
如果引入了 CDN,那么解析的流程可能会稍微复杂一点,大家有空自己去了解一下。比如阿里云就提供了 cdn 的功能。

HTTP 协议通信原理

域名被成功解析以后,客户端和服务端之间,是怎么建立连接并且如何通信的呢? 说到通信,大家一定听过 tcp 和 udp 这两种通信协议,以及建立连接的握手过程。而 http 协议的通信是基于 tcp/ip 协议之上的一个应用层协议,应用层协议除了 http 还有哪些呢(FTP、 DNS、SMTP、Telnet 等)。
涉及到网络协议,我们一定需要知道 OSI 七层网络模型和 TCP/IP 四层概念模型,OSI 七层网络模型包含(应用层、表示层、会话层、传输层、网络层、数据链路层、物理层)、TCP/IP 四层概念模型包含(应用层、传输层、网络层、数据链路层)。

网络分层模型

7层是指OSI七层协议模型,主要是:应用层(Application)、表示层(Presentation)、会话层(Session)、传输层(Transport)、网络层(Network)、数据链路层(Data Link)、物理层(Physical)。
在这里插入图片描述
具体每一层对应的协议如下图:
在这里插入图片描述
在这里插入图片描述
图片转载至:https://blog.csdn.net/buknow/article/details/81148684

请求发起过程,在 tcp/ip 四层网络模型中所做的事情

当应用程序用 TCP 传送数据时,数据被送入协议栈中,然后逐个由上至下通过每一层直到被当作一串比特流送入网络。其中每一层对收到的数据都要增加一些首部信息(有时还要增加尾部信息)
在这里插入图片描述

在这里插入图片描述
客户端如何找到目标服务

  1. 客户端发起请求

  2. 在数据链路层组装目标机器的 MAC 地址

    目标机器的 mac 地址如何得到呢? 这里涉及到一个 ARP 协议,这个协议简单来说就是已知目标机器的 ip,需要获得目标机器的 mac 地址。(发送一个广播消息,这个 ip 是谁的,请来认领。认领 ip 的机器会发送一个 mac 地址的响应),可以得到这个目标 MAC 地址

    为了避免每次都用 ARP 请求,机器本地也会进行 ARP 缓存。当然机器会不断地上线下线, IP 也可能会变,所以 ARP 的 MAC 地址缓存过一段时间就会过期。

  3. 数据包在链路上广播,服务器的网卡发现并接收数据包。

  4. 服务器的网卡把包接收进来,然后打开 IP 包,发现 IP 地址也是自己的,再打开 TCP 包,发现端口是自己,也就是 80 端口,而这个时候这台机器上有一个 nginx 是监听 80 端口。 于是将请求提交给 nginx,nginx 返回数据。

  5. 将数据发回请求的机器。层层封装,最后到 MAC 层。因为来的时候有源 MAC 地址,返回的时候,源 MAC 就变成了目标 MAC,再返给请求的机器。

接收端收到数据包以后的处理过程
当目的主机收到一个以太网数据帧时,数据就开始从协议栈中由下层向上层传递,同时去掉各层协议加上的报文首部。每层协议都要去检查报文首部中的协议标识,以确定接收数据的上层协议。

在这里插入图片描述
TCP/IP 的分层管理

TCP/IP 协议按照层次分为 4 层:应用层、传输层、网络层、数据链路层。对于分层这个概念, 大家一定不陌生,比如我们的分布式架构体系中会分为业务层、服务层、基础支撑层。比如 docker,也是基于分层来实现。所以我们会发现,复杂的程序都需要分层,这个是软件设计的要求,每一层专注于当前领域的事情。如果某些地方需要修改,我们只需要把变动的层替换掉就行,一方面改动影响较少,另一方面整个架构的灵活性也更高。 最后,在分层之后, 整个架构的设计也变得相对简单了。

分层负载

  • 二层负载均衡
    二层负载是针对 MAC,负载均衡服务器对外依然提供一个 VIP(虚 IP),集群中不同的机器 采用相同 IP 地址,但是机器的 MAC 地址不一样。当负载均衡服务器接受到请求之后,通过 改写报文的目标 MAC 地址的方式将请求转发到目标机器实现负载均衡
    二层负载均衡会通过一个虚拟 MAC 地址接收请求,然后再分配到真实的 MAC地址
  • 三层负载均衡
    三层负载是针对 IP,和二层负载均衡类似,负载均衡服务器对外依然提供一个 VIP(虚 IP), 但是集群中不同的机器采用不同的 IP 地址。当负载均衡服务器接受到请求之后,根据不同的 负载均衡算法,通过 IP 将请求转发至不同的真实服务器
    三层负载均衡会通过一个虚拟 IP 地址接收请求,然后再分配到真实的 IP 地址
  • 四层负载均衡
    四层负载均衡工作在 OSI 模型的传输层,由于在传输层,只有 TCP/UDP 协议,这两种协议 中除了包含源 IP、目标 IP 以外,还包含源端口号及目的端口号。四层负载均衡服务器在接受 到客户端请求后,以后通过修改数据包的地址信息(IP+端口号)将流量转发到应用服务器。
    四层通过虚拟 IP + 端口接收请求,然后再分配到真实的服务器
  • 七层负载均衡
    七层负载均衡工作在 OSI 模型的应用层,应用层协议较多,常用 http、radius、dns 等。七层 负载就可以基于这些协议来负载。这些应用层协议中会包含很多有意义的内容。比如同一个 Web 服务器的负载均衡,除了根据 IP 加端口进行负载外,还可根据七层的 URL、浏览器类 别来决定是否要进行负载均衡
    七层通过虚拟的 URL 或主机名接收请求,然后再分配到真实的服务器。

TCP/IP 协议的深入分析

通过前面一个案例的分析,基本清楚了网络的通信流程,在 http 协议中,底层用到了 tcp 的通信协议,我们接下来给大家简单介绍一下 tcp 的通信协议原理

通信协议,我们接下来给大家简单介绍一下 tcp 的通信协议原理。 我们如果需要深入学习网络协议,就要先把一些基本的协议的作用和工作过程搞清楚,网络 设备还没智能到人脑的程度,它是由人类创造出来的,它的工作过程肯定是符合人类的交流 习惯并按照人类的交流习惯来设计的。所以要以人类的思维方式去理解这些协议。 例如,你给别人打电话,不可能电话一接通你就啪啦啪啦地说一大通,万一对方接通电话后 因为有事还没来得及倾听呢?这不太符合正常人类的交流习惯。一般是电话接通后,双方会 有个交互的过程,会先说一声“你好”,然后对方也回复一声“你好”,双方通过各自一句“你好” 明确对方的注意力都放在了电话沟通上,然后你们双方就可以开始交流了,这才是正常的人 类交流方式,这个过程体现在计算机网络里就是网络协议!我们通过 TCP 协议在两台电脑建 立网络连接之前要先发数据包进行沟通,沟通后再建立连接,然后才是信息的传输。而 UDP 协议就类似于我们的校园广播,广播内容已经通过广播站播放出去了,你能不能听到,那就 与广播站无关了,正常情况下,不可能你说没注意听然后再让广播站再播放一次广播内容。 基于这些思路,我们先去了解下 TCP 里面关注比较多的握手协议

TCP 握手协议 (建立连接时用)

TCP 消息的可靠性首先来自于有效的连接建立,所以在数据进行传输前,需要通过三次握手建立一个连接,所谓的三次握手,就是在建立 TCP 链接时,需要客户端和服务端总共发送 3 个包来确认连接的建立,在 socket 编程中,这个过程由客户端执行 connect 来触发
在这里插入图片描述

  1. 第一次握手:(SYN=1, seq=x) 客户端发送一个 TCP 的 SYN 标志位置 1 的包,指明客户端打算连接的服务器的端口,以及初始序号 X,保存在包头的序列号 (Sequence Number)字段里。 发送完毕后,客户端进入 SYN_SEND 状态。
  2. 第二次握手:(SYN=1, ACK=1, seq=y, ACKnum=x+1): 服务器发回确认包 (ACK) 应答 。 即 SYN 标志位和 ACK 标志位均为 1。服务器端选择自己 ISN 序列号,放到 Seq 域里,同时将确认序号 (Acknowledgement Number)设置为客户的 ISN 加 1, 即 X+1。 发送完毕后,服务器端进入 SYN_RCVD 状态。
  3. 第三次握手:(ACK=1 ,ACKnum=y+1) 客户端再次发送确认包(ACK),SYN 标志位为 0,ACK 标志位为 1,并且把服务器发来 ACK 的序号字段+1,放在确定字段中发送给对方,并且在数据段放写 ISN 发完毕后,客户端进入 ESTABLISHED 状态。当服务器端接收到这个包时,也进入 ESTABLISHED 状态,TCP 握手结束。

小知识点:SYN攻击

在三次握手过程中,Server 发送 SYN-ACK 之后,收到 Client 的 ACK 之前的 TCP 连接称为 半连接(half-open connect),此时 Server 处于 SYN_RCVD 状态,接着,当收到 ACK 后,Server 转入 ESTABLISHED 状态。

SYN 攻击就是 Client 在短时间内伪造大量不存在的 IP 地址,并向 Server 不断地发送 SYN 包,Server 回复确认包,并等待 Client 的确认,由于源地址是不存在的,因此,Server 需要不断重发直至超时,这些伪造的 SYN 包将占用未连接队列,导致正常的 SYN 请求因为队列满而被丢弃,从而引起网络堵塞甚至系统瘫痪。

SYN 攻击时一种典型的 DDOS 攻击,检测 SYN 攻击的方式非常简单,即当 Server 上有大量半连接状态且源 IP 地址是随机的,则可以断定遭到 SYN 攻击了

TCP 四次挥手协议 (断开连接时用)

四次挥手表示 TCP 断开连接的时候,需要客户端和服务端总共发送 4 个包以确认连接的断开; 客户端或服务器均可主动发起挥手动作(因为 TCP 是一个全双工协议),在 socket 编程中, 任何一方执行 close() 操作即可产生挥手操作。

概念解释:

  • 单工:数据传输只支持数据在一个方向上传输
  • 半双工:数据传输允许数据在两个方向上传输,但是在某一时刻,只允许在一个方向上传输,实际上有点像切换方向的单工通信
  • 全双工:数据通信允许数据同时在两 个方向上传输,因此全双工是两个单工通信方式的结合,它要求发送设备和接收设备都有独立的接收和发送能力

四次挥手图示:
在这里插入图片描述

  1. 第一次挥手(FIN=1,seq=x)
    假设客户端想要关闭连接,客户端发送一个 FIN 标志位置为 1 的包,表示自己已经没有数据可以发送了,但是仍然可以接受数据。发送完毕后,客户端进入 FIN_WAIT_1 状态。
  2. 第二次挥手(ACK=1,ACKnum=x+1)
    服务器端确认客户端的 FIN 包,发送一个确认包,表明自己接受到了客户端关闭连接的请求, 但还没有准备好关闭连接。发送完毕后,服务器端进入 CLOSE_WAIT 状态,客户端接收到这个确认包之后,进入 FIN_WAIT_2 状态,等待服务器端关闭连接。
  3. 第三次挥手(FIN=1,seq=w)
    服务器端准备好关闭连接时,向客户端发送结束连接请求,FIN 置为 1。发送完毕后,服务器 端进入 LAST_ACK 状态,等待来自客户端的最后一个 ACK。
  4. 第四次挥手(ACK=1,ACKnum=w+1)
    客户端接收到来自服务器端的关闭请求,发送一个确认包,并进入 TIME_WAIT 状态,等待可能出现的要求重传的 ACK 包。
    服务器端接收到这个确认包之后,关闭连接,进入 CLOSED 状态。 客户端等待了某个固定时间(两个最大段生命周期,2MSL,2 Maximum Segment Lifetime) 之后,没有收到服务器端的 ACK,认为服务器端已经正常关闭连接,于是自己也关闭连接, 进入 CLOSED 状态。

白话解释:

假设 Client 端发起中断连接请求,也就是发送 FIN 报文。Server 端接到 FIN 报文后,意思是 说"我 Client 端没有数据要发给你了",但是如果你还有数据没有发送完成,则不必急着关闭 Socket,可以继续发送数据。所以你先发送 ACK,“告诉 Client 端,你的请求我收到了,但是 我还没准备好,请继续你等我的消息”。这个时候 Client 端就进入 FIN_WAIT 状态,继续等待 Server 端的 FIN 报文。当 Server 端确定数据已发送完成,则向 Client 端发送 FIN 报文,“告 诉 Client 端,好了,我这边数据发完了,准备好关闭连接了”。Client 端收到 FIN 报文后,"就 知道可以关闭连接了,但是他还是不相信网络,怕 Server 端不知道要关闭,所以发送 ACK 后 进入 TIME_WAIT 状态,如果 Server 端没有收到 ACK 则可以重传。“,Server 端收到 ACK 后, “就知道可以断开连接了”。Client 端等待了 2MSL 后依然没有收到回复,则证明 Server 端已 正常关闭,那好,我 Client 端也可以关闭连接了。Ok,TCP 连接就这样关闭了!

问题:

  1. 为什么连接的时候是三次握手,关闭的时候却是四次握手?
    答:三次握手是因为因为当 Server 端收到 Client 端的 SYN 连接请求报文后,可以直接发送 SYN+ACK 报文。其中 ACK 报文是用来应答的,SYN 报文是用来同步的。
    但是关闭连接时, 当 Server 端收到 FIN 报文时,很可能并不会立即关闭 SOCKET(因为可能还有消息没处理完),所以只能先回复一个 ACK 报文,告诉 Client 端,“你发的 FIN 报文我收到了”。只有等到 我 Server 端所有的报文都发送完了,我才能发送 FIN 报文,因此不能一起发送。故需要四步挥手。
  2. 为什么 TIME_WAIT 状态需要经过 2MSL(最大报文段生存时间)才能返回到 CLOSE 状态?
    答:虽然按道理,四个报文都发送完毕,我们可以直接进入 CLOSE 状态了,但是我们必须假设网络是不可靠的,有可以最后一个 ACK 丢失。所以 TIME_WAIT 状态就是用来重发可能丢失的 ACK 报文。

猜你喜欢

转载自blog.csdn.net/nonage_bread/article/details/111193131
今日推荐