深入解析Http请求背后的秘密(上)

前言

我们用了那么久的浏览器,但是我们知道在输入一个网址到界面响应这背后的到底发生了什么吗?为什么我们输入www.baidu.com,它就知道我们找的是百度的地址呢?我们都知道我们按下回车之后触发的是http请求,但是http请求到底是什么,为什么它就能够请求到我们的数据呢?作为一名程序猿,探索和了解下我们的所处的网络世界,我觉得还是很有

由于篇幅有限,不可能把所有细节都理清楚,因此尽可能抓我们平时都会接触到的内容来做解析,一些不太需要了解的,就简单说明一下了。同时针对每个人获取信息的目的不同,我将先简要的概括Http请求的整个流程,然后再进行具体的分析和阐述。各位看官根据自己的时间和目的来是否需要全篇看完,如果对你有用,记得一键三连哟~

概述

从我们输入网址或者点击某个链接开始,到最终接受到web服务器返回的消息并展示大致分为下面几个过程。

  1. 解析HTTP请求
  2. 创建HTTP连接
  3. 请求的发送和应答
  4. 断开连接

下面我们来开始具体的阐述每个过程发生的事情,本篇文章重点分析1、2步骤,3、4步骤放到下篇文章。

在讲解之前,我先来讲个我们身边例子。

我们想要给某个人寄信,我们需要做什么呢,首先我们肯定需要知道寄到哪,寄给谁吧,这是最基本的问题了,但是这其实也是存在问题的,这个地址我们怎么确定才能够保证所有的人都知道这是哪呢?那就肯定需要一个规范的地址,比如XXX省XXX市XXX区XXX号等,但是如果我们只知道某个宏观上的地点呢?比如XXX公司,但是不知道具体的门牌号怎么办呢?那我们在寄信的时候,要么就是我们自己百度下,明确具体的街道门牌号,然后写上,要么就是邮局工作人员帮我们输入地址的时候会自动查出是在哪个街道哪一号。明确了地点、收件人,我们可以写好信的内容,然后用信封来装好,最后递交给邮局。到这里,我们就寄信完成了,只需等待回信即可。

说了这么多,可能大家会有点迷糊,这个和我们的网络请求发送又有什么联系吗?且听我慢慢道来。

一、解析HTTP请求

写文章之前,我看了很多的文章在描述http请求的时候,第一步都是建立TCP连接。但是其实都忽略了一个原则性问题,我们想要修一条路,我们总得知道,我们这条路是修到哪的吧?也就是明确我们的目的地。所以,一个Http请求发生后最开始做的事应该是去解析这个请求链接,然后分析出我们的目的信息,如ip地址、访问的文件路径、服务端的端口等。

Http请求链接解析

开始讲解之前,不妨先了解下我们每天都在接触的网络链接到底是啥样的,下面用一个http链接来举例:

http://www.yoka.com/dna/222/192/index.html

上面的链接主要包含这几块内容:协议类型、域名/IP地址、端口号、文件路径。上面的链接可以如下拆分:

协议类型:http
域名/IP地址:www.yoka.com
端口号:web服务器默认80端口,可省略不写
文件路径:/dna/222/192/index.html

协议类型

扫描二维码关注公众号,回复: 12806507 查看本文章

浏览器支持的协议类型分为多种:http、https、ftp、news、mailto等,news、mailto很少用到,这里不讲。ftp协议是文件传输协议,主要用来上传和下载文件时用到,也不过多阐述。主要讲讲http和https两者的区别。

Http协议:超文本传输协议,是一个基于请求与响应,无状态的,应用层的协议,常基于TCP/IP协议传输数据,互联网上应用最为广泛的一种网络协议,所有的WWW文件都必须遵守这个标准。目前http协议的主流版本是http2.0,http2.0支持多路复用、服务器推送、头信息压缩、二进制协议等,多路复用即指通过单一的HTTP/2连接请求发起多重的请求-响应消息,多个请求stream共享一个TCP连接,实现多留并行而不是依赖建立多个TCP连接。

Https协议:HTTPS是一种通过计算机网络进行安全通信的传输协议,经由HTTP进行通信,利用SSL/TLS建立全信道,加密数据包。对传入的内容加密,采用混合加密技术,中间者无法直接查看明文内容,同时支持验证服务器的身份,通过证书认证客户端访问的是自己的服务器,也能够有效的保证数据的完整性等。
参考: HTTP和HTTPS协议,看一篇就够了

域名/IP地址 & DNS

正常情况,绝大多数的网页链接都是采用域名去访问,这是因为域名能够代表对应网站的特点,比如:www.baidu.com,而如果用ip地址显示,一串数字不仅不方便记忆,同时也没啥特色。但是通过域名是无法正确的找到我们的web服务器的地址的,这就需要用到DNS(域名服务系统)

我们每个人的电脑上都会自带一个DNS客户端,简称解析器。查询域名对应的IP地址即为域名解析的过程。我们发起http请求时,最终的连接处理其实会让我们的操作系统来执行,这个时候,操作系统就会通过解析器向DNS服务器发起域名解析的请求,DNS服务器解析域名后返回对应的IP地址,解析器会将IP地址取出然后写入浏览器制定的内存地址中。但是访问web服务器我们需要知道它的IP地址,我们又是怎么知道DNS服务器的IP地址呢?这个其实在我们电脑上本身就配好了的,如下:

在这里插入图片描述
至此,我们就能正常得到web服务器的IP地址了。但是IP地址为什么又能找到我们对应的服务器地址呢,这又要对IP地址有所了解。我们所有的电脑都会分配一个IP地址,而ip地址主要由两部分构成:网络号、主机号。网络号为主机所在的网络的一个子网编号,主机号则对应的是我们的计算机。一个IP地址是一串32比特的数字,8bit为一组分为四组,然后再用圆点做分割,ip地址中主机号和网络号的占比是不固定的,所以需要有一个子网掩码来标识。具体如下:

  1. IP地址主体标识方法
10.11.12.13
  1. 采用与IP地址相同格式标识子网掩码的方法
//后者为子网掩码,子网掩码为1的部分(十进制转比特)标识网络号,为0标识主机号
//所以下面的ip地址,网络号为10.11.12,主机号为13
10.11.12.13/255.255.255.0   

值得提一句的是,主机后部分的比特全部为0或者全部为一是代表两种特殊的含义,为0代表整个子网而不是子网中的某个设备,为1代表向子网的所有设备发送包,即广播。

至此,我们就已经拿到了我们域名对应的ip地址了,也就知道了我们这一次请求的目的地了,剩下的就是遇水搭桥,创建一个发送方和服务器之间可通信的连接了。

二、创建HTTP连接

当我们已经知道服务器的ip地址之后,我们最终的发送请求,其实是需要操作系统底层来实现的,这里用到的就是操作系统内部的协议栈,协议栈在处理网络请求时,主要分两个步骤:创建套接字、连接服务器。这里先放一张大致的操作系统通信层级图。
在这里插入图片描述

创建套接字

我们要创建一个连接管道,最关键的就在于管道两端的数据出入口,这些出入口称为套接字,浏览器通过调用Socket库中的socket程序来创建套接字,套接字创建好之后,才能进行管道的连接。具体的流程如下:

  1. 服务端启动并创建好套接字,进入等待状态,等待客户端连接管道。
  2. 客户端创建套接字,然后延伸出管道,最后管道连接到服务器端的套接字上。
  3. 收发数据。
  4. 客户端或服务器断开连接,双方删除套接字。

那套接字到底是啥呢?可以理解为它们只是存在于操作系统内存空间的一串数据信息,在创建套接字的时候,系统会为期开辟一个内存空间,并写入套接字的初始状态(需要注意的是这个时候连接信息IP地址、端口号等还并没有传入到套接字中,只是单纯创建了个初始状态),并为每个套接字分配一个描述符,用以区分不同套接字。这些信息用于控制通信操作,主要包含了通信对象的IP地址、端口号、通信操作的进行状态等。控制信息可以分成两类,一类是在创建连接请求的时候,这些控制信息会被放到连接信息的头部(TCP头部),每次请求都需要带上这些控制信息的。具体如下:
在这里插入图片描述
上面主要需要了解的有以下几个:

  • 32位确认号(ACK号):接收方用来告知发送方接收到所有数据的第几个字节。
  • 32位序列号:发送方告知接收方该网络包发送的数据相当于所有数据的第几个字节。
  • ACK:标识接收数据序列号字段有效,一般表示已被接收方接受到
  • SYN:发送方和接收方相互确认序号,表示连接操作。
  • FIN:表示断开连接
    实际发送的时候,其实是像下面这样:
    在这里插入图片描述

还有一类则是存放在套接字中,用来控制协议栈操作的信息。
协议栈在创建连接的时候,就需要基于这些控制信息来操作。window系统下,其实可以通过命令来看套接字内容的,具体命令为:netstat -ano

连接服务器

在创建完套接字后,浏览器就会调用Socket库中的connect应用程序将本地套接字和服务器套接字进行连接,在调用connect的时候会将服务器的ip地址和端口号一并传入。具体类似如下:

connect(<描述符>, <服务器的端口和ip>,...)

连接主要是做了以下一些事情:

  1. 将服务器的IP地址和端口号告诉协议栈;
  2. 客户端向服务器传达开始通信的请求;
  3. 创建临时存放收发数据的内存空间,及缓冲区;

其中客户端向服务端传达开始通信的请求首先便是在TCP模块处创建表示连接控制信息的头部,也就是我们上面那个表格的内容。通过TCP的头部信息可以找到发送方和接收方的端口号,然后再向下传递给IP模块,在请求的前面加上IP的头部信息并进行网络包的返送操作,最后网络报就会通过网络到达服务器,服务器在对其依此进行IP、TCP模块的逐层解析,找到对应的套接字信息,然后再从服务器中等待状态的套接字中匹配出端口号一致的即可。到这一步,就开启了网络通信中常说的三次握手的第一次握手。剩下的两次握手,数据的处理过程都和第一次类似,就不再详细阐述。这里简单说下,分别是服务器返回已接收的响应,客户端在接收到服务器返回的相应之后,即说明连接成功,最后客户端再根据返回的响应请求,向服务端发送一个确认接收的反馈请求,告诉服务器刚才的响应包已经收到。到这里连接才算真正的完成了!

至于客户端是如何知道连接是成功的呢,这就要用到我们说的每次请求我们都会包含的请求头,其中的控制标识ACK和SYN等,具体的大致如下:

在这里插入图片描述
到这,客户端就已经成功连接上了服务器了,简单概括下就是:浏览器首先解析我们的请求url(通常都是http://ip地址/访问的文件路径),根据url的内容(如果是一个域名,比如www.baidu.com,则需要从DNS服务器上获取该域名对应的ip地址)调用操作系统的应用程序(Socket库中的socket和connect等)来创建好套接字,并通过协议栈逐层向下,完成TCP连接。
在这里插入图片描述
原创不易,欢迎一键三连~

参考资料:

《网络是怎样连接的》

TCP头部格式

猜你喜欢

转载自blog.csdn.net/dypnlw/article/details/113525055
今日推荐