浏览器一个请求过程
整个流程如下:
域名解析
为了将消息从你的PC上传到服务器
上.需要用到1P协议、ARP协议和0SPF协议
发起TCP的3次握手
建立TCP连接后发起http请求
服务器响应htp请求
浏览器解析htm代码,并请求html代码中的资源(如js、css、图片等)
断开TCP连接
浏览器对页面进行渲染呈现给用户
一、域名解析的详细内部过程
例如,要查询www.baidu.com的IP地址(DNS解析url):
浏览器搜索自己的DNS缓存(维护一张域名与IP地址的对应表)
若没有,则搜索操作系统中的DNS缓存(维护一张域名与IP地址的对应表)
若没有,则搜索操作系统的hosts文件(Windows环境下,维护一张域名与IP地址的对应表,位置一般在 C:\Windows\System32\drivers\etc\hosts)
若没有,则操作系统将域名发送至 本地域名服务器- -(递归查询方式),本地域名服务器 查询自己的DNS缓存,查找成功则返回结果,否则,(以下是迭代查询方式)
4.1 本地域名服务器 向根域名服务器(其虽然没有每个域名的具体信息,但存储了负责每个域,如com、net、org等的解析的顶级域名服务器的地址)发起请求,此处,根域名服务器返回com域的顶级域名服务器的地址
4.2 本地域名服务器 向com域的顶级域名服务器发起请求,返回baidu.com权限域名服务器(权限域名服务器,用来保存该区中的所有主机域名到IP地址的映射)地址
4.3 本地域名服务器 向baidu.com权限域名服务器发起请求,得到www.baidu.com的IP地址
本地域名服务器 将得到的IP地址返回给操作系统,同时自己也将IP地址缓存起来
操作系统将 IP 地址返回给浏览器,同时自己也将IP地址缓存起来
至此,浏览器已经得到了域名对应的IP地址
二、三次握手
第一次握手:主机A发送位码为syn=1,随机产生seq number=x的数据包到服务器,客户端进入SYN_SEND
状态,等待服务器的确认;主机B由SYN=1知道,A要求建立联机;
第二次握手:主机B收到请求后要确认联机信息,向A发送ack number(主机A的seq+1),syn=1,ack=1,随机产生seq=y的包,此时服务器进入SYN_RECV
状态;
第三次握手:主机A收到后检查ack number是否正确,即第一次发送的seq number+1,以及位码ack是否为1,若正确,主机A会再发送ack number(主机B的seq+1),ack=1,主机B收到后确认seq值与ack=1则连接建立成功。客户端和服务器端都进入ESTABLISHED
状
态,完成TCP三次握手。
TCP位码,有6种标示:SYN(synchronous建立联机) ACK(acknowledgement 确认) PSH(push传送) FIN(finish结束) RST(reset重置) URG(urgent紧急)
Sequence number(顺序号码) Acknowledge number(确认号码)
三、建立TCP连接后发起http请求
四、服务器收到请求并响应HTTP请求
1.负载均衡
网站可能会有负载均衡设备来平均分配所有用户的请求。即对工作任务进行平衡,分
摊到多个操作单元上执行,如图片服务器,应用服务器等。
2请求处理阅读请求及它的参数和 cookies
五.浏览器解析htm代码,并请求htm代码中的资源(如js、css图片等)
看是否是长连接。来决定是不是断开TCP连接
六.断开TCP连接
四次挥手
第一次挥手:主机1(可以使客户端,也可以是服务器端),设置Sequence Number
和Acknowledgment Number
,向主机2发送一个FIN
报文段;此时,主机1进入FIN_WAIT_1
状态;这表示主机1没有数据要发送给主机2了;
第二次挥手:主机2收到了主机1发送的FIN
报文段,向主机1回一个ACK
报文段,Acknowledgment Number
为Sequence Number
加1;主机1进入FIN_WAIT_2
状态;主机2告诉主机1,我也没有数据要发送了,可以进行关闭连接了;
第三次挥手:主机2向主机1发送FIN
报文段,请求关闭连接,同时主机2进入CLOSE_WAIT
状态;
第四次挥手:主机1收到主机2发送的FIN
报文段,向主机2发送ACK
报文段,然后主机1进入TIME_WAIT
状态;主机2收到主机1的ACK
报文段以后,就关闭连接;此时,主机1等待2MSL后依然没有收到回复,则证明Server端已正常关闭,那好,主机1也可以关闭连接了。
七.浏览器对页面进行渲染呈现给用户
重新温习下网络模型:
- 七层结构(至顶向下):应用层、表示层、会话层、传输层、网络层、数据链路层、物理层
client(浏览器) 与Server 通过HTTP协议通讯,HTTP协议属于”应用层协议”;HTTP基于TCP协议,TCP通过Socket进行通讯,TCP 被称为“传输层协议”。而HTTPS 还需要走会话层SSL\TLS等协议;传输层之下是网络层,这里主要是路由协议OSPF等进行路由选择,转发;再向下数据链路层主要是ARP、RARP协议完成IP和MAC地址互相解析,再向下是物理层主要是基于IEEE802.X等协议进行数据比特流转成高低电平的定义;
当浏览器发出请求时候,首先通过应用层DNS协议得到对应IP地址,在这经历全球路由大接力;而传输层TCP协议采用“三次握手”协议建立连接和“四次挥手”协议断开连接,然后数据链路层解析IP与MAC地址的映射;数据经过层层数据封包、解包过程,如下:
这里特别强调下三次握手建立连接,放图作为参考:
四次握手断开连接:
客户端发起 FIN ACK, 服务端应答 ACK, 待服务端数据发送完成后,发送FIN ACK, 客户端应答 ACK, 连接断开。
从应用服务角度分析
数据交换主要通过HTTP 协议, HTTP协议是无状态协议。多数通过GET、POST方法,GET与POST区别:
GET:请求获取指定的资源,不改变服务器状态,GET方法是幂等的,GET方法的报文主体没有任何语义。
POST: 根据请求报文主体对指定的资源做出处理,改变服务器状态,POST方法不幂等。
http方法不仅只有GET、POST, http1.1中含有如下方法:
RESTful API 就是利用这组方法来统一表述资源的状态转化。
同时,由于http无状态协议的特点,服务端需要记录用户时,就需要用某种机制来识具体的用户, 通常采用cookies、session。
session 本意是会话,是一个抽象概念。将 clinet 和 server 之间一对一的交互,抽象为“会话”,开发者为了实现一对一的“隔离”,中断和继续等操作,进而衍生出“会话状态”,也就是 session 的概念。
如何维护这个session概念,很自然的想到在http请求报文中加入登录标识就可以了,这个登录标识就是cookie。而 cookie 是一个实际存在的东西,http 协议中定义在 header 中的字段。这种技术的实现就是利用了cookie技术。 cookie是存储key-value对的一个文件,务必记住,它是由服务器将cookie添加到response里一并返回给客户端,然后客户端会自动把response里的cookie接收下来,并且保存到本地,下次发出请求的时候,就会把cookie附加在request里,服务器在根据request里的cookie遍历搜索是否有与之符合的信息。
cookie 虽然很方便,但是使用 cookie 有两个的弊端:
- cookie 中的所有数据在客户端就可以被修改。这就意味着数据非常容易被伪造,一些重要的数据就不能存放在 cookie 中;
- 如果 cookie 中数据字段太多会影响传输效率;
为了解决这些问题,就产生了 session,
session是一种服务器机制,使用Hash散列表结构来保存信息。
1. 每个 session 都对应一个 session_id,通过 session_id 可以查询到对应的 session;
2. session_id 通常是存放在客户端的 cookie 中,服务端存好 session 之后将对应的 session_id 设置在 cookie 中发送给客户端;
3. 当请求到来时,服务端检查 cookie 中保存的 session_id 并通过这个 session_id 与服务器端的 session 关联起来,进行数据的保存和修改;
这就是大多数人通常所说的session, 这里其实是指的 session实现。
server 端通常采用Nginx、Apache;
这里以PHP为例:
Nginx接收到请求,进行一些验证,如黑白名单拦截等, 是否有限流限制,是否有负载均衡设置;
如果请求的是静态内容,Nginx会将结果直接返回给用户。
如果请求的是动态内容,Nginx会将请求交给fastcgi客户端, 通过fastcgi_pass将这个请求发送给进程php-fpm。Nginx 不支持对外部动态程序的直接调用或者解析 ,所有的外部程序必须通过FastCGI接口来调用。