星驰编程网

免费编程资源分享平台_编程教程_代码示例_开发技术文章

一个网址引发的技术大爆炸(二)_一个网站的网址组成

引言

当我在浏览器上输入一个珍藏已久的网址之后,回车加载的那一刻,作为牛马猿的我突然就萌发了一个好奇心,从网址加载到最后页面渲染,中间到底涉及了哪些技术?在我片刻思考之后,就发现我的技术栈炸了...

网络报文传输

继上一篇,我研究了浏览器是如何通过www.baidu.com能访问到百度的,其中涉及域名解析,IP寻址,以及这个请求是如何从我们家里的电脑层层转发给百度的过程。那么问题来了,我们进行一个网站的访问,这个访问的请求是怎么在我们的电脑里边进行转换,又是怎么在网络里传播的呢?

TCP/IP五层模型

  • 应用层

当我们浏览器输入www.baidu.com时,默认会访问https://www.baidu.com,这里就明确了应用层http协议,即基于http报文格式包装数据,服务端接收到请求之后,同样按照当前格式进行解析。由于是https则在表示层会进行SSL加解密,然后会话层会根据http协议版本,控制会话逻辑,比如在http1.0版本时,可以基于keep-alive设置,一次TCP链接进行多次http报文请求,但仍有“队头阻塞”问题——如果响应1很慢,会阻塞后面的请求2、3,等到了http2.0就已经支持多路复用,多个请求和响应可以并行交错传输,彻底解决了队头阻塞。

在TCP/IP五层模型中,对ISO七层里的应用层、表示层、会话层统一为应用层,因为这三个都有应用层负责。

POST /api/v1/login HTTP/1.1
Host: www.baidu.com
Content-Type: application/json
Content-Length: 45

{
"username": "root",
"password": "123456"
}
  • 传输层

在应用层明确了报文格式以及表示绘画逻辑之后,就需要开始进行链接建立,http应用层协议链接的建立是依靠TCP(Transmission Control Protocol)传输控制协议来实现的。在通过DNS域名解析流程获取百度目标地址IP之后,就开始进行TCP三次握手进行链接建立,并对数据报文进行封装:[TCP头] + [HTTP报文],这里在进行三次握手时,双方需要确定数据传输的最大传输单元(MTU),然后最大的报文长度(MSS)= MTU - TCP头 - IP头,所以当HTTP报文太长的时候,就需要拆分。

TCP头关键信息:源端口(随机高端口,如 54321),目的端口(80 HTTP服务标准端口),序列号(一个随机初始值,如 1000),标志位(ACK=1, PSH=1,催促接收方立即上传数据)

  • 网络层

在传输层进行TCP报文包装和传输数据拆分之后,在网络层会进行数据单元的包装,即IP数据包:[IP头] + [TCP头] + [HTTP报文],其中IP头关键信息:源IP地址(你电脑的局域网IP,如 192.168.1.100)、目的IP地址(百度服务器的公网IP,如 14.215.177.38)、协议字段(6 代表上层是TCP)、TTL(64 生存时间,每经过一个路由器减1,防止数据包无限循环)

  • 链路层

在要进行数据传输前,电脑需要先根据子网掩码判定是否同一局域网,如果是则基于ARP协议广播询问目标IP电脑的MAC地址,如果不是则询问路由器MAC地址,然后对IP数据包进行封装:[帧头] + [IP头] + [TCP头] + [HTTP报文] + [帧尾],其中帧头关键信息:目标MAC地址(路由器WAN口/局域网目的电脑的MAC地址)、源MAC地址(电脑网卡的MAC地址)、类型(0x0800 代表载荷是IP数据包);帧尾:FCS(帧校验序列),用于检测传输错误

  • 物理层

在通过链路层最后的封装之后,数据则可以在网络中传播,网卡将报文数据转成比特流,然后根据物理介质将其转换成电信号或是电磁波,然后路由器收到之后,还原成比特流组装成以太网帧,然后数据会先通过交换机,检查MAC地址,发现是局域网内交互,则直接进行报文转发,当发现MAC地址是路由器,则路由器先进行拆包,并且检查IP头,决策路由方向之后,将IP头中的原IP替换成路由器的IP,将帧头的源MAC地址替换成路由器的MAC地址,同时记录“源IP:源高位端口 - 路由器IP:路由器随机端口”映射关系,在重新封装以太网帧之后,把数据发送到下一个路由器,下一个路由器同理进行拆包和装包,直到最后消息发送到目标电脑。

TCP三次握手、四次挥手、确认机制

  • 三次握手

A与B之间进行一次TCP连接,需要经历三次的数据交互,第一次A发送一个TCP报文给B,其中报文段的SYN标志位为1,表示这是一个连接的请求,同时会随机选择一个初始序列号ISN,比如Seq=x,放在报文中,此时A的连接状态为SYN_SENT。

第二次在B收到A的SYN报文之后,如果同意建立连接,则回复一个报文段,并设置两个标志位:SYN=1和ACK=1,同时随机生成自己的初始化序列号,比如Seq=y,然后将确认号Ack设置为x+1,表示收到了序列号x,下次从x+1开始发送,此时B的状态为SYN-RCVD。

第三次A收到B的SYN-ACK报文之后,再给B发送一个确认报文,报文ACK标志位设置为1,其中序列号Seq=x+1,Ack= y + 1,此时两边都变成ESTABLISHED状态,连接建立成功。

为什么是三次握手,不是两次?

假设只有两次握手:如果A发送的一个旧的SYN请求延迟了很久才到达B,B会误以为A要建立新连接,于是回应SYN-ACK并一直等待A发送数据,造成B的资源浪费。而三次握手下,A不会确认那个旧的SYN-ACK,B收不到确认就会超时关闭连接。

  • 四次挥手

四次挥手,是一个连接断开的四部操作,假设又客户端发起断开请求,第一次发送一个FIN报文段(FIN=1),序列号为u(等于客户端已经传送的数据的最后一个字节的序列号加1)。客户端进入FIN_WAIT_1状态。

第二次服务器收到FIN报文段后,发送一个ACK报文段(ACK=1),确认号为u+1,序列号为v(服务器自己的序列号),服务器进入CLOSE_WAIT状态。客户端收到这个ACK后,进入FIN_WAIT_2状态。此时,从客户端到服务器的连接已经关闭,但服务器到客户端的连接还可以传输数据。

第三次当服务器也没有数据要发送时,服务器会发送一个FIN报文段(FIN=1),序列号为w(可能等于v,也可能大于v,因为中间可能又发送了数据),确认号仍为u+1,服务器进入LAST_ACK状态。

第四次挥手客户端收到服务器的FIN报文段后,发送一个ACK报文段(ACK=1),确认号为w+1,序列号为u+1。客户端进入TIME_WAIT状态,等待2MSL(Maximum Segment Lifetime,最大报文段生存时间)后进入CLOSED状态。服务器收到ACK后,立即进入CLOSED状态。

为什么需要四次挥手?

因为TCP是全双工的,关闭操作需要独立进行。当A说“我发完了”时,B可能还有数据要发送,所以不能立即回复FIN。必须等B也发完所有数据后,才能发送FIN。因此,ACK和FIN分成了两个步骤。

为什么A最后要等待2MSL?

MSL是报文最大生存时间。确保B能收到最后的ACK:如果这个ACK丢失,B会超时重传FIN。等待2MSL可以保证A有足够的时间收到这个重传的FIN并再次发送ACK。让本次连接的旧报文在网络中消逝:防止旧的、延迟的报文段被新的、相同IP和端口的连接错误地接收。

  • 确认机制

在网络中传输数据,一定就会存在数据丢失的情况,那是怎么保证网络报文不丢失的呢?那就是传输层TCP的重试与确认机制了。

首先在建立连接和断开连接时,请求双方都会对收到请求进行进行确认,比如SYN-建立连接、ACK-确认、FIN-断开连接,如果在等待时长未收到确认,则会重新发送,直到达到重试次数。

同理在进行数据传输时,也会有确认机制,假设发送方要发送3000字节的数据,MSS为1000字节。发送方将数据分成3段发送:Seq=1000, 长度1000, Seq=2000, 长度1000, Seq=3000, 长度1000。接收方成功收到第1段(Seq=1000)和第3段(Seq=3000),但第2段(Seq=2000)丢失。收到第1段后,接收方发送 ACK=2000,收到第3段(失序)后,接收方无法按序确认,于是连续发送重复的 ACK=2000。如果启用了SACK,会附带信息告知已收到3000-4000的数据块。发送方收到第3个 ACK=2000 时,触发快速重传,立即重传第2段(Seq=2000)。接收方收到重传的第2段后,此时1、2、3段都已按序收到,于是发送一个累积确认 ACK=4000,表明3000字节数据全部接收成功。

传输加密HTTP+SSL

数据在网络中传播时,经常疑惑的就是,会不会有黑客对网络进行报文监听,这样传输的数据不就完全暴露在网络中了吗?答案是肯定的,不仅存在监听还存在假冒和网络中间商,所以为了保证数据网络的传输安全,引入了SSL,即HTTP + SSL = HTTPS。

加密算法

在聊HTTPS之前,需要先对加密算法有一定的认识,加密算法一般分为两类,对称加密和非对称加密算法,其中对称加密算法只有一个密钥,加解密都是用一个密钥,速度快,但是密钥只有一个不好保管,相关算法有AES、SM4;而非对称加密算法则有两个密钥,一个公钥一个私钥,公钥可以直接公开,其中公钥加密得私钥解密,私钥加密得公钥解密,这样密钥好管理了但是性能会有一定的下降,相关算法有RSA、SM2。

其中非对称加密算法的典型使用场景有以下两种:

数据加密:客户端使用公钥加密,保证只有服务端的私钥才能解密。很多时候,服务器A和B,自身既是客户端又是服务端,所以需要A和B都有自己的一套公钥和私钥,其中公钥公开,私钥自己保留。

数字签名:数字签名要解决的问题是,保证数据是私钥方发出并且数据未被篡改,但是不保证数据被别人截取。其中私钥方对数据进行加密,同时对数据进行Hash计算,以及带上明文的公钥,即对数据签名,接收方收到数据之后,获取公钥,对数据进行解密并同样对数据进行Hash之后进行数据对比,确保数据未被篡改。

HTTPS请求流程

浏览器在基于HTTPS访问服务器地址时,首先会下载该服务器的CA证书,该CA证书由服务端申请共用户访问时下载,用户浏览器下载CA证书之后首先验证CA证书的合法性,然后获取CA证书中的服务器提供的公钥,同时生成一个随机数作为数据对称加密的秘钥,通过公钥加密之后,发送给服务端,其中CA证书的秘钥是保密存放在服务端,服务端通过秘钥解密得到对称加密的秘钥,则后续数据的传输通过对称密钥对数据加密即可完成数据的加密传输。

针对HTTPS使用场景疑问:

Q:用户访问服务器,比如访问百度,怎么确保发送的请求以及返回给用户的公钥确实是百度的,而不是劫持人伪装的百度?

A:无法保证,所以针对公钥和私钥,需要由第三方信任机构进行申请与颁发。

Q:CA证书是如何保证证书的防伪的?

A:CA证书有一对公钥和私钥,其中私钥为CA机构持有,会对CA证书的相关信息进行加密,并且对证书信息进行摘要,用户下载证书之后,第一步就是通过CA证书上用于验伪的公钥对证书信息进行解密,并且针对证书信息进行摘要处理,将得到的结果与CA证书上的摘要信息进行比较,进而确保证书的真实性。

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言