HTTP-点开浏览器输入网址背后发生的那点事
前言
Internet最早来源于美国国防部ARPANet,1969年投入运行,到现在已有很长一段路了,各位想要了解发展史可以百度下,这里就不多说了。
现如今当我们想要获取一些资料,首先是打开某个浏览器,在地址栏输入地址,想要的信息出现在你的面前。
大家有没有想过输入地址就能返回给你想要的信息是怎么实现的呢?
下面就来简单说下它的实现流程,不过在这之前先来了解下HTTP基本概念如下
HTTP基本概念
在这引用http://www.zsythink.net/archives/76
这是一篇为初学者准备的文章,所以作者会尽量从基础出发,尽量细致的描述每一个细节,以求让初学者不会一头雾水,有一定基础的同学就不用看了,以免浪费你的时间。
假设博主今天春心荡漾,想要访问一些不可描述的小网站,于是,博主悄悄的打开了浏览器,在浏览器的地址栏中输入了一个小网站的网址,
此处假设这个小网站的网址为 www.zsythink.net ,当博主输入了这个网址以后,浏览器中就显示了博主想要看到的内容,整个过程如下图所示。
那么,浏览器返回给我们的内容是怎么产生的呢?
这些内容肯定不是凭空产生的,而是有人为我们准备了这些内容,当我们在浏览器的地址栏中输入网址以后,
这些提前准备好的内容即可返回到浏览器中,以便有需要的人能够查看到这些内容,
而查看这些内容的人就是我们平常所说的"客户",客户往往会通过"客户端程序"去请求、查看这些内容,
我们最常使用的客户端程序就是浏览器了,所以,在之后的http相关的文章中,
如果没有特别说明,我们所说的"客户端"就是指"浏览器",我们使用客户端去查看我们想要的内容,
而提供内容的一端被称为"服务端",当作为客户时,我们需要在电脑上安装客户端软件(即浏览器),
通过客户端软件查看我们想要的内容,而作为提供内容的人,也需要在服务端的计算机上安装对应的软件,
才能为我们提供服务,而服务端的计算机就是我们常说的"服务器",安装在服务器上的、为我们提供内容的软件被称之为"web服务器软件"。
所以,综上所述,我们可以了解到如下名词
注:如下名词的解释均针对http而言,在后面的文章中我们会解释什么是http,此处不用纠结
客户端:客户端通常是指浏览器,比如谷歌浏览器、火狐浏览器、IE等,浏览器安装在客户使用的电脑上,所以,在描述http时,客户端通常也代指那些安装了浏览器的电脑。
服务端:服务端通常是指那些安装了"web服务软件"的计算机,这些服务端的计算机被称为服务器。
没错,聪明如你一定想到了,说白了,客户端与服务端就是两台电脑,分别安装了不同的软件,服务端提供内容,客户端查看内容。
所以,当我们访问网页时,大致的过程如下图所示。
客户端与服务端既然能够通讯,那么证明它们之间一定是通过某种方法进行沟通的,就像你我之间能够进行沟通一样。
举例说明
你和我都说汉语,所以,当我说"苹果"这个词的时候,你就会想到一种水果,或者想到一个手机品牌,
但是当我对一个美国人说"苹果"两个字时,他可能并不能理解我在说什么,因为他可能听不懂汉语,
如果我想要对他表达"苹果"这个词,我需要说"Apple",他才会明白我说的是什么,当我跟你聊天时,我们都说汉语,
当两个美国人聊天时,他们都说英语,这样,才能有效的沟通,总之,如果想要能够顺畅的沟通,
沟通双方都必须遵守相同的协议,我们可以把汉语理解成一种协议,把英语也理解成一种协议,
只要沟通双方都遵守相同的协议,双方就能够顺畅的沟通,只要沟通双方都遵守相同的协议,双方就能够理解对方想要做什么。
当然,之所以拿汉语、英语举例,是为了让初学者能够更加容易的理解"协议"这个词,但是请不要错误的以为"协议"就是"语言",
之所以拿语言举例,是为了方便理解,说白了,"协议"可以理解为某种规则或者某种约定,
只要大家都严格按照这种约定行事,世界就会正常的运转,比如"红灯停,绿灯行"也可以理解为一种协议,
比如在马路上都要靠右行驶(在中国),也是一种协议,比如在小饭馆,你给老板人民币,老板给你对应的餐食,
也是一种协议,"协议"的概念稍微有一些抽象,稍微有一些宽泛,此处大概有一个印象即可,在学习的过程中,我们自己就会慢慢的理解它了。
客户端与服务端之间,也需要遵守某些相同的协议,才能够顺畅的通讯,细心如你一定注意到了,我说的是"某些"协议,也就是说,双方要遵守的协议不止有一种,它们需要同时遵守多种协议,才能够正常的完成整个通讯过程。
比如http协议,刚才已经说过,不同的"层面"中,需要使用不同的协议,http协议就是应用层的一种协议,http协议是什么意思呢?
http是HyperText Transfer Protocol的缩写,HyperText Transfer Protocol译为"超文本传输协议"。
从字面上理解,这种协议是用来传输"超文本"的,我们可以暂且粗暴的将"超文本"理解成我们所谓的"网页"(这样并不准确,但是方便理解),那么,我们可以将http协议理解为一种"网页传输协议"。
…
…
一次完整的HTTP请求过程
web服务请求处理步骤
HTTP服务通信过程
人性化HTTP请求相应图
图片来自:理解Http请求与响应
大致如下
域名解析 --> TCP3次握手 --> 发起http请求 --> 服务器响应http请求并传输数据 –> 浏览器解析并渲染呈现给用户 –> TCP4次挥手
域名解析
当用户在浏览器输入https://www.cnblogs.com/时,浏览器会对此域名或主机进行解析,得到对应的IP地址,那么它时怎么进行域名解析的呢?
1、首先先去本机hosts文件查找此FQDN没有没定义的指向所在的IP地址条目,如果找到,就结束解析
2、如果没有找到,回去浏览器器本身DNS缓存里去寻找,找打结束解析
3、没有找到,会去本机配置的首选DNS服务器查询,一般这是三大运营商提供的,通过UTP53端口发起请求,这个请求是递归查询,DNS服务器收到请求后,会查询自身缓存,找到条目并且没有过期,就返回给用户,结束解析。如果没有找到,它会去找根服务器,全球13个根服务器(根服务器地址本机DNS服务器内置),询问根服务器(你知不知道一个域名叫“www.cnblogs.com”的IP地址),根回复说,(我不知道此域名的IP地址,但我知道com域的IP地址,你去询问它吧),于是运行商提供的DNS服务器就去询问com这个域,(你知不知道一个叫“www.cnblogs.com”域名IP地址),com域回答你说,(我不知道此域名的IP地址,但我知道“cnblogs.com域的IP地址,你去问他吧“),这是运行商DNS服务器,对cnblogs.com域发起请求询问,(你知不知道一个叫”www.cnblogs.com“域的IP地址,它一查,发现此域,就是它负责的,就会对你说,此域是我负责的,它的IP是X.X.X.X这时运行商DNS服务器拿到地址,就会返回客户主机内核,内核再返回给浏览器,到此解析结束,进行下一步。
当然这里面还要涉及到IP –> MAC(物理地址)的解析
TCP3次握手
浏览器拿到域名对应的IP后,会拿一个随机端口向WEB服务程序80端口发起TCP请求链接
备注:
SYN(synchronous建立联机)
ACK(acknowledgement 确认)
PSH(push传送)
FIN(finish结束)
RST(reset重置)
URG(urgent紧急)
Sequence number(顺序号码)
Acknowledge number(确认号码)
举例
A : 你好我是A,你能听得到我说话吗?
B : 听到了,我是B,你能听到我说话吗?
A : 可以,听到了
好建立连接,开始聊天!
过程
第一次握手:建立连接,客户端将SYN标记为1,seq标记为x,并将SYN包发送到服务器,并进入SYN_SEND状态,等待服务器确认;
第二次握手:服务器收到SYN,知道客户端要建立链接,同时向客户端也发送一个SYN包(SYN=1)和一个ACK包(ACK=1),随机产生一个数seq=y,ack=x+1(客户端的seq值x加1),来确认客户端的SYN,并进入SYN_RECV;
第三次握手:客户端收到服务器发来的SYN+ACK后,确认ack值,并回复服务器端一个ACK确认,发送完毕后,双方进入ESTABLISHED状态。
三次握手成功后,开始传输数据。
一个完整的三次握手也就是 请求---应答---再次确认
链接建立成功后,就要开始下一步,传输数据
HTTP请求相应处理
1、建立TCP连接:
接收或拒绝连接请求
发送请求报文
2、接收请求:
接收客户端发来的请求报文中的信息对某资源的一次请求的过程
Web访问响应模型(Web I/O)
1)单进程I/O模型:
启动一个进程处理用户请求,而且一次只处理一个,多个请求被串行响应
2)多进程I/O模型:
并行启动多个进程,每个进程响应一个连接请求
3)复用I/O结构:
启动一个进程,同时响应N个连接请求
实现方法: 多线程模型和事件驱动
多线程模型: 一个进程生成N个线程,每线程响应一个连接请求
事件驱动: 一个进程处理N个请求
4)复用的多进程I/O模型:
启动M个进程,每个进程响应N个连接请求,同时接收M*N个请求
3、处理请求:
服务器对请求报文进行解析,并获取请求的资源及请求方法等相关信息,根据方法,资源,首部和可选的主体部分对请求进行处理
HTTP常用请求方式,Method
GET、POST、HEAD、PUT、DELETE、TRACE、OPTIONS
4、访问资源:
服务器获取请求报文中请求的资源web服务器,即存放了web资源的服务器,负责向请求者提供对方请求的静态资源,或动态运行后生成的资源
资源放在服务端特定的目录下
备注:通过MAC地址和端口号确定具体的应用程序
5、构建响应报文:
一旦Web服务器识别除了资源,就执行请求方法中描述的动作,并返回响应报文。响应报文中 包含有响应状态码、响应首部,如果生成了响应主体的话,还包括响应主体
6、发送响应报文
向客户端回复报文
7、记录日志:
最后,当事务结束时,Web服务器会在日志文件中添加一个条目,来描述已执行的事务
备注:这中间还要涉及到https的建立过程
数据传输完毕就要断开链接了
四次挥手
如图
备注:
数据传输完毕后,双方都可释放连接。最开始的时候,客户端和服务器都是处于ESTABLISHED状态,然后客户端主动关闭,服务器被动关闭。
过程
- 客户端进程发出连接释放报文,并且停止发送数据。释放数据报文首部,FIN=1,其序列号为seq=u(等于前面已经传送过来的数据的最后一个字节的序号加1),此时,客户端进入FIN-WAIT-1(终止等待1)状态。 TCP规定,FIN报文段即使不携带数据,也要消耗一个序号。
- 服务器收到连接释放报文,发出确认报文,ACK=1,ack=u+1,并且带上自己的序列号seq=v,此时,服务端就进入了CLOSE-WAIT(关闭等待)状态。TCP服务器通知高层的应用进程,客户端向服务器的方向就释放了,这时候处于半关闭状态,即客户端已经没有数据要发送了,但是服务器若发送数据,客户端依然要接受。这个状态还要持续一段时间,也就是整个CLOSE-WAIT状态持续的时间。
- 客户端收到服务器的确认请求后,此时,客户端就进入FIN-WAIT-2(终止等待2)状态,等待服务器发送连接释放报文(在这之前还需要接受服务器发送的最后的数据)。
- 服务器将最后的数据发送完毕后,就向客户端发送连接释放报文,FIN=1,ack=u+1,由于在半关闭状态,服务器很可能又发送了一些数据,假定此时的序列号为seq=w,此时,服务器就进入了LAST-ACK(最后确认)状态,等待客户端的确认。
- 客户端收到服务器的连接释放报文后,必须发出确认,ACK=1,ack=w+1,而自己的序列号是seq=u+1,此时,客户端就进入了TIME-WAIT(时间等待)状态。注意此时TCP连接还没有释放,必须经过(最长报文段寿命)的时间后当客户端撤销相应的TCB后,才进入CLOSED状态。
- 服务器只要收到了客户端发出的确认,立即进入CLOSED状态。同样,撤销TCB后,就结束了这次的TCP连接。可以看到,服务器结束TCP连接的时间要比客户端早一些。
问题1-为什么连接的时候是三次握手,关闭的时候却是四次握手?
答:
因为当Server端收到Client端的SYN连接请求报文后,可以直接发送SYN+ACK报文。其中ACK报文是用来应答的,
SYN报文是用来同步的。但是关闭连接时,当Server端收到FIN报文时,很可能并不会立即关闭SOCKET,
所以只能先回复一个ACK报文,告诉Client端,"你发的FIN报文我收到了"。只有等到我Server端所有的报文都发送完了,
我才能发送FIN报文,因此不能一起发送。故需要四步握手。
问题2-为什么要三次握手
答:
为了防止已失效的连接请求报文段突然又传送到了服务端,因而产生错误。
网上转载的例子不错:
三次握手:
A:“喂,你听得到吗?”A->SYN_SEND
B:“我听得到呀,你听得到我吗?”应答与请求同时发出 B->SYN_RCVD | A->ESTABLISHED
A:“我能听到你,今天balabala……”B->ESTABLISHED
四次挥手:
A:“喂,我不说了。”A->FIN_WAIT1
B:“我知道了。等下,上一句还没说完。Balabala…..”B->CLOSE_WAIT | A->FIN_WAIT2
B:”好了,说完了,我也不说了。”B->LAST_ACK
A:”我知道了。”A->TIME_WAIT | B->CLOSED
A等待2MSL,保证B收到了消息,否则重说一次”我知道了”,A->CLOSED
参考链接
1、http://www.zsythink.net/archives/76
2、https://blog.csdn.net/qzcsu/article/details/72861891