当你在浏览器输入一个URL后,在应用层和运输层 会发生以下动作:
-
查询IP地址
-
建立连接
-
收发数据
-
断开连接
查询IP地址
首先浏览器会将URL中的域名提取出来,并通过以下过程 获取该域名所对应的IP地址
1、浏览器
浏览器检查自己的缓存,如果有,则获取到IP地址
若没有,则调用操作系统 Socket库中的解析器(一个名为 gethostbyname的组件)
2、解析器
同样,解析器检查自己的缓存,如果有,则直接返回结果
如果没有,则向最近的路由器发出查询
3、路由器
距离客户端最近的路由器检查自己的缓存,如果有,则直接返回结果
如果没有,则向本地DNS服务器发出查询
4、DNS查询
本地DNS服务器检查自己的缓存,如果有,则直接返回结果
如果没有,则依次向根服务器、顶级域DNS服务器、权威DNS服务器发出递归查询
成功获取到IP地址后,客户端的浏览器就会生成HTTP请求报文
并委托协议栈发送HTTP请求,进入下一阶段
建立连接
HTTP协议规定使用TCP作为运输层的协议,因此,我们以TCP为例
1、创建套接字
浏览器调用协议栈中的 socket 组件,为套接字分配内存
并生成一个用以识别套接字的描述符,放在浏览器内存中
套接字的实体就是通信的控制信息,包括 服务器的IP地址,客户端和服务器的端口号等
2、建立TCP连接
浏览器调用协议栈中的 connect 组件,并附加3个参数(描述符,服务器IP地址,端口号)
于是通信双方开始进行TCP的“三次握手”
关于“三次握手”的具体过程,请看这篇文章
成功建立TCP连接后,进入下一阶段
收发数据
1、客户端发送数据
浏览器调用 write 将要发送的数据 交给协议栈
协议栈先将数据存放在内部的发送缓冲区,等待一定时间后再发送
有2个因素会影响协议栈发送网络包的时间:
-每个网络包能容纳的数据长度(MSS)是有限的
-网络延迟
如果以时间优先,那么每个网络包内的数据量可能很小,传输效率降低
如果以网络包中的数据量优先(等到网络包装满再发送),那么可能会增加网络延迟
2、客户端接收数据
服务器返回响应后,客户端的浏览器调用 read 将控制流程转移到协议栈
协议栈将收到的来自服务器的数据 暂存到缓冲区,并按顺序连接起来
然后取出数据 传递给浏览器
断开连接
一般来说,完成数据发送的一方 会主动发起断开连接的请求
首先,应用程序调用 close 委托协议栈 发送FIN报文
于是通信双方开始进行TCP的“四次挥手”
关于“四次挥手”的具体过程,请看这篇文章
最后,主动发送断开连接请求的一方 经过 TIME-WAIT 之后,删除套接字,释放端口号