输入一个URL后发生了什么?
- 1.DNS应用层协议解析域名
- 2.传输层TCP建立连接
- 3.应用层客户端发送HTTP请求
- 4.网络层
- 5.数据链路层
- 6.服务器处理请求
- 7.关闭TCP连接
- 8.浏览器解析HTML,浏览器布局渲染
1.DNS应用层协议解析域名
网络的传输是靠ip地址,而我们输入的一般是域名如www.baidu.com。所以我们需要用DNS把域名转换为对应的ip地址。
客户端先检查本地hosts是否有对应的IP地址,若找到则返回响应的IP地址。若没找到则请求上级DNS服务器,直至找到或到根节点。
2.传输层TCP建立连接
“三次握手”的过程是,发送端先发送一个带有SYN(synchronize)标志的数据包给接收端,在一定的延迟时间内等待接收的回复。接收端收到数据包后,传回一个带有SYN/ACK标志的数据包以示传达确认信息。接收方收到后再发送一个带有ACK标志的数据包给接收端以示握手成功。在这个过程中,如果发送端在规定延迟时间内没有收到回复则默认接收方没有收到请求,而再次发送,直到收到回复为止。
3.应用层客户端发送HTTP请求
Http请求报文结构
http报文结构由请求行,请求头,空行、请求正文组成(Get请求,没有请求正文)
请求行:请求方法、url、版本号
请求头:Host:接收请求的服务器地址,可以是ip也可以是端口号
User-Agent:发送请求的应用程序名称
Connection:指定与连接相关的属性,Connection:Keep-Alive
Accept-Charset:指定可接收的编码格式
Accept-Encoding:指定可接收的数据压缩格式
Accept-Language:指定可以接收的语言
可能会有Cookie,保存用户的登录信息,在服务器响应时会在Cookie中存放sessionid来标识这个用户。
空行:表示请求头结束
请求正文:可选,get就没有请求正文
4.网络层
整个跨设备数据传输过程如下:
A发出目的地为C的IP数据报,查询本地路由表发现下一跳为E
A将数据报发送给E
E查询本地路由表发现下一跳为F,将数据报发送给F
F查询本地路由表发现目的地C,是和自己直接连接的,然后将数据报发送给C
ip数据包会通过路由表来规划一系列到达目标ip的路线。IP数据包的传输过程也和问路一样:
当IP数据包, 到达路由器时, 路由器会先查看目的IP;
路由器决定这个数据包是能直接发送给目标主机, 还是需要发送给下一个路由器;
依次反复, 一直到达目标IP地址。
如何判断要转发给哪个路由器?
每个路由器都维护一个路由表,会根据目的ip查询路由表,如果查到了就从指定的网络接口进行发送(路由器上有很多网线接口);如果没找到,就从默认的WAN口转发给下一个路由器。
5.数据链路层
下边结合数据链路层和网络层,看整个过程:
第一步:
A发出目的地为C的IP数据报,查询路由表发现下一跳为E
A将IP数据报交给数据链路层,并告知目的MAC地址是E
数据链路层填充源MAC地址A和目的MAC地址E
数据链路层通过物理层将数据发送给E
第二步:
E的数据链路层接收到数据帧,把数据帧传输给网络层
E查询路由表,发现下一跳为F
E把数据交给数据链路层并告知目的MAC地址为F
E的数据链路层封装数据帧并发送(此时源MAC地址和目的MAC地址就会发生变化,源MAC地址为E,目的MAC地址为F)
第三步:
F的数据链路层接收到数据帧,把数据帧交给网络层
F查询路由表,发现下一跳为C
F把数据交给数据链路层,并告知目的MAC地址为C
F的数据链路层封装数据帧并发送
根据网络层可知下一个路由器的IP地址,ARP协议可以将IP地址解析成对应的MAC地址。当通信的双方不在同一个局域网时,需要多次中转才能到达最终的目标,在中转的过程中需要通过下一个中转站的MAC地址来搜索下一个中转目标。
6.服务器处理请求
服务接收到客户端发送的HTTP请求后,查找客户端请求的资源,并返回响应。
Http响应报文结构
http响应报文由状态行、响应头、空行、响应正文四部分组成
状态行:协议版本、状态码、状态描述,之间用空格分开
响应头:Server:服务器应用程序软件的名称和版本号
Content-Type:相应正文的类型(是图片还是二进制)
Content-Length:相应正文的长度
Content-Charset:相应正文的使用编码
Content-Encoding:相应正文使用的数据压缩格式
Content-Language:相应正文使用的语言
空行:表示响应头结束
响应正文
7.关闭TCP连接
客户端主动调用close,向服务器发送结束报文段FIN,服务器返回确认报文段ACK,当服务器处理完之前的数据后调用close,发送结束报文段FIN,客户端收到并返回ACK,服务器收到ACK后彻底关闭连接。
客户端的记时等待TIME_WAIT 是为了防止ACK丢包。