在浏览器中输入网址按下回车经历了一个怎样的过程?
总的来说分为以下几个过程:
1、DNS解析:将域名解析为IP地址;
2、TCP连接:TCP三次握手;
3、发生HTTP请求;
4、服务器处理请求并返回HTTP报文;
5、浏览器解析渲染页面;
6、断开连接:TCP四次挥手;
下面为大家一一介绍以上过程:
DNS 协议提供通过域名查找 IP 地址,或逆向从 IP 地址反查域名的服务。DNS 是一个网络服务器,我们的域名解析简单来说就是在 DNS 上记录一条信息记录。
网页通过向DNS服务器发送域名,DNS服务器查询到与域名相应的IP地址,然后返回给浏览器,浏览器在将IP地址打印在协议上,同时请求参数也会在协议搭载,然后一并发送给对应的服务器。
1.浏览器会发一个同步序列号syn给服务器,通知服务器建立连接。(告诉服务器我要发送请求)
2.服务器收到后,根据传过来的同步序号syn,返回同步序号syn和ack包。(告诉浏览器我准备接收了,你发送吧)
3.为了证明服务器传过来的信息有效性,浏览器会返回ack包给服务器。(告诉服务器,我马上发送,准备接收)
为什么要发起三次握手:
为了防止已失效的连接请求报文段突然又传送到服务端,因而产生错误
疑惑:为什么三次握手必须是三次呢?
第一种情况:假如只有一次,浏览器发信息过去服务器,服务器能不能通信都不知道,那样不就浪费浏览器资源。
第二种情况:假如两次,假设这种情况 ↓
前提 ,我们要清楚,浏览器发送信号给服务器,这个信号是有时效,如果信号失效,浏览器会再次发送信号给服务器,失效信号得到的返回数据将不再有效。
由于信号的时效性,服务器出现卡顿或者重启的情况。浏览器的第一次等待数据太过长,选择作废第一次请求,执行第二次推送同步信号。
在此情景中,服务器会现后返回两次ack包给浏览器,但是第一次的数据浏览器已经作废了,浏览器只认第二次请求数据的帐。
但是服务器不知道浏览器这样子,哪个有效,哪个无效,假如浏览器不告诉服务器,服务器会认为请求成功,傻傻的等待浏览器发送请求,第二种情况还好,假如出现第一种,不就白白浪费资源。
所以,浏览器收到数据会返回一个ack包给服务器,哪次响应是有效的,这样才不会浪费过多的资源。
1.建立tcp连接后,浏览器会发送请求(请求方法+请求头+请求体)给服务器,获取对应数据。
2.但是服务器执行到响应是需要时间的,不可能一下子就給你响应数据,想想你的sql查询耗时过长?所以就需要发送一个ack包告诉浏览器。
3.服务器执行成功后就立马返回给浏览器响应数据。
4.浏览器得到响应数据就会返回ack数据包告知服务器。
疑惑:为什么响应后浏览器不发数据给服务器,告诉浏览器收到?假如不告诉,服务器会不停发送响应给浏览器吗?
解释:是有告诉服务器收到,这里就需要四次挥手了。
疑惑:请求到响应可不可以省去服务器发送给用户的ack包?
解释:不能,刚刚也说过浏览器信号的时效性,如果请求收到,到响应返回这个时长过长,浏览器会再次发送请求给服务器。
在TCP三次握手结束后,开始发送HTTP请求报文
请求报文由请求行、请求头、请求体三部分组成:
1.请求行包含请求方法、URL、协议版本
请求方法包含 8 种:
GET、POST、PUT、DELETE、PATCH、HEAD、OPTIONS、TRACE。
URL 即请求地址,由 <协议>://<主机>:<端口>/<路径>?<参数> 组成
协议版本即 http 版本号
POST /chapter17/user.html HTTP/1.1
“POST” 代表请求方式
“/chapter17/user.html”表示URL
"HTTP/1.1"代表协议和协议的版本。
2.请求头包含请求的附加信息,由关键字/值对组成,每行一对,关键字和值用英文冒号“:”分隔。
请求头部通知服务器有关于客户端请求的信息。它包含许多有关的客户端环境和请求正文的有用信息。其中比如:Host,表示主机名,虚拟主机;Connection,HTTP/1.1 增加的,使用 keepalive,即持久连接,一个连接可以发多个请求;User-Agent,请求发出者,兼容性以及定制化需求。
3.请求体,可以承载多个请求参数的数据,包含回车符、换行符和请求数据,并不是所有请求都具有请求数据。
name=tom&password=1234&realName=tomson
上面代码,承载着 name、password、realName 三个请求参数。
1. 服务器
服务器是网络环境中的高性能计算机,它侦听网络上的其他计算机(客户机)提交的服务请求,并提供相应的服务,比如网页服务、文件下载服务、邮件服务、视频服务。而客户端主要的功能是浏览网页、看视频、听音乐等等,两者截然不同。 每台服务器上都会安装处理请求的应用——web server。常见的 web server 产品有 apache、nginx、IIS 或 Lighttpd 等。web server 担任管控的角色,对于不同用户发送的请求,会结合配置文件,把不同请求委托给服务器上处理相应请求的程序进行处理(例如 CGI 脚本,JSP 脚本,servlets,ASP 脚本,服务器端 JavaScript,或者一些其它的服务器端技术等),然后返回后台程序处理产生的结果作为响应。
2. MVC 后台处理阶段
后台开发现在有很多框架,但大部分都还是按照 MVC 设计模式进行搭建的。 MVC 是一个设计模式,将应用程序分成三个核心部件:模型(model)-- 视图(view)–控制器(controller),它们各自处理自己的任务,实现输入、处理和输出的分离。
1、视图(view):它是提供给用户的操作界面,是程序的外壳。
2、模型(model):模型主要负责数据交互。在 MVC 的三个部件中,模型拥有最多的处理任务。一个模型能为多个视图提供数据。
3、控制器(controller):它负责根据用户从"视图层"输入的指令,选取"模型层"中的数据,然后对其进行相应的操作,产生最终结果。
3.http 响应报文
响应报文由响应行(request line)、响应头部(header)、响应主体三个部分组成。
(1) 响应行包含:协议版本,状态码,状态码描述
状态码规则如下:
1xx:指示信息–表示请求已接收,继续处理。
2xx:成功–表示请求已被成功接收、理解、接收。
3xx:重定向–要完成请求必须进行更进一步的操作。
4xx:客户端错误–请求有语法错误或请求无法实现。
5xx:服务器端错误–服务器未能实现合法的请求。
(2) 响应头部包含响应报文的附加信息,由 名/值 对组成
(3) 响应主体包含回车符、换行符和响应返回数据,并不是所有响应报文都有响应数据
1.当发送请求后,浏览器就会发送final包给服务器要求断开连接了。(请求报文发送完了,你准备关闭吧)
2.服务器接收后,也是需要处理完之前的响应,才能进行关闭的。避免浏览器误认为没有发送到服务器,从而进行二次发送。服务器会先发送一个ack包给浏览器,告诉浏览器收到断开请求。(接收完请求报文,我准备关闭,你也准备吧)
3.等服务器关闭资源后,发送final包给浏览器,表示可以关闭了。(响应报文发送完毕,你准备关闭吧)
4.浏览器收到,也需响应服务器返回一个ack包,然后两边断开连接。(响应报文接收完毕,我准备关闭,你也准备吧)
疑惑:第四次ack数据包有必要吗?
解释:有必要,服务器发送final包,不确定是否发送到浏览器,就会继续发送,知道收到ack数据包才断开连接。
疑惑:服务器发送ack包和final包期间,这段时间在做什么?
解释:服务器会去判断效应数据是否已经发送。
因为存在网络异常的问题,导致推迟发送。同时也因为浏览器还没接收到数据就向服务器发送final包,这样子服务器没处理完就收到final包了。
所以在这段时间里,服务器会判断数据是否已经发送,发送的话就返回final包给浏览器。
疑惑:服务器发送ack包和final包期间,是怎么知道自己发的响应浏览器已经收到了?
解释:当发送请求后,浏览器就会发送final包给服务器要求断开连接了。在这个流程里面。浏览器是会接收到响应的,同时是需要返回一个ack包给服务器,告诉数据接收到。服务器会根据自己需要发送的响应数据和自己得到的ack作比较,如果都接收就发送final包给浏览器,没有就其余操作。
疑惑:浏览器怎么判断第一次挥手成功?
解释:浏览器发送final数据包后会进入fin_wait_1状态(第一次等待fin信号),服务器收到会返回ack包,并且进入close_wait状态(等待关闭),如果浏览器一直没收到ack包,就会重复发送fin数据包,直到收到ack包变成fin_wait_2状态(第二次等待fin数据包)。
疑惑:第四次挥手,浏览器知道自己发送成功吗?如果发送失败,服务器不就一直等待?
解释:当浏览器收到fin数据包后,浏览器不会立即关闭连接。会处于2分钟的待机时间。
站在服务器角度,服务器收不到浏览器发送的ack包,会一直发送fin包给浏览器,直到浏览器返回ack包。
在浏览器的待机时间里,它会判断服务器还有没有fin包发过来,有代表发送ack包给服务器失败,没有会自行断开。
当客户端要与服务端断开连接的时候,会向服务端发一个final的报文,当服务端接收到这个报文的时候,就知道客户端要与自己断开连接了,此时服务端会向客户端发送一个消息确认消息ack包,告诉客户端,我接受到了你的断开连接的请求,但是此时还不能断开,因为此时服务端可能还没做好断开连接的准备,可能会有之前请求的数据没有发送完,当服务端确保自己数据已经全发送完之后,会向客户端发送一个final的报文,告诉客户端,我已经准备好了,可以断开连接,客户端同样也要给服务端发送一个消息确认ack的报文,告诉服务端,我接收到你的回应。这就是为什么挥手,比握手多一次的原因。