一、浏览器首先会对URL进行解析
下面以http://www.server.com/dir1/file1.html为例
当没有路径名时,就代表访问根目录下事先设置的默认文件,也就是 /index.html
或者 /default.html
对URL进行解析之后,浏览器确定了 Web 服务器和文件名,就会根据这些信息来生成 HTTP 请求消息。
但是光有web服务器名www.server.com是不够的,只知道一个人的名字肯定是找不到人的,我们还需要服务器的IP地址。
而DNS服务器就可以通过服务器名提供它的IP地址(相当于一个电话本,通过人名查询电话号码),
DNS域名是分层级的,越靠右层级越高。
例如www.server.com实际上是www.server.com.(多了后面的.)
- 根 DNS 服务器(.)
- 顶级域 DNS 服务器(.com)
- 权威 DNS 服务器(server.com)
在寻找IP地址时,会先在浏览器缓存中寻找是否有和目标服务器名对应的IP地址,如果没有,则会到操作系统缓存中寻找,如果没有再问hosts文件中寻找,还是没有,才会到本地DNS服务器中去寻找,如果还是没有,那么本地DNS服务器会到根DNS服务器中进行询问,根服务器发现是.com后缀,就说你去问.com顶级域名服务器吧,而.com顶级域名服务器会让你去问负责www.server.com的权威域名服务器,权威 DNS 服务器查询后将对应的 IP 地址 X.X.X.X 告诉本地 DNS服务器。
本地 DNS 再将 IP 地址返回客户端,客户端和目标建立连接。
通过 DNS 获取到 IP 后,就可以把 HTTP 的传输工作交给操作系统中的协议栈。
协议栈包括上下两部分,上半部分是负责收发数据的 TCP 和 UDP 协议,这两个传输协议会接受应用层的委托执行收发数据的操作。下半部分用 IP 协议控制网络包收发操作,在互联网上传数据时,数据会被切分成一块块的网络包,而将网络包发送给对方的操作就是由 IP 负责的。
IP 中还包括 ICMP
协议和 ARP
协议。
ICMP
用于告知网络包传送过程中产生的错误以及各种控制信息。ARP
用于根据 IP 地址查询相应的以太网 MAC 地址。
随后HTTP报文需要依次组装TCP头部,IP头部和MAC头部来形成网络包,组装完成后如图所示:
下面对组装过程进行讲解。
二、组装TCP头部
源端口号和目标端口号:确认数据应该发给哪个应用。
序号:解决包乱序的问题。
确认号:确认发出去对方是否有收到。如果没有收到就应该重新发送,直到送达,这个是为了解决丢包的问题。
状态位:SYN
是发起一个连接,ACK
是回复,RST
是重新连接,FIN
是结束连接等。TCP 是面向连接的,因而双方要维护连接的状态,这些带状态位的包的发送,会引起双方的状态变更。
窗口大小:TCP 要做流量控制,通信双方各声明一个窗口(缓存大小),标识自己当前能够的处理能力,别发送的太快或太慢。
除了做流量控制以外,TCP还会做拥塞控制,对于真正的通路堵车不堵车,它会控制发送的速度。
在 HTTP 传输数据之前,首先需要 TCP 建立连接,TCP 连接的建立,通常称为三次握手,目的是保证双方都有发送和接收的能力。
TCP 的连接状态查看,在 Linux 可以通过 netstat -napt
命令查看。
如果 HTTP 请求消息比较长,超过了 MSS
的长度,这时 TCP 就需要把 HTTP 的数据拆解成一块块的数据发送。
MTU
:一个网络包的最大长度,以太网中一般为1500
字节。MSS
:除去 IP 和 TCP 头部之后,一个网络包所能容纳的 TCP 数据的最大长度。- 数据会被以
MSS
的长度为单位进行拆分,并对每个被拆分的数据加上 TCP 头信息,然后交给 IP 模块来发送数据。
三、组装IP头部
假设客户端有多个网卡,就会有多个 IP 地址,那 IP 头部的源地址应该选择哪个 IP 呢?
这个时候就需要根据路由表规则,来判断哪一个网卡作为源地址 IP。
在 Linux 操作系统,我们可以使用 route -n
命令查看当前系统的路由表。
我们的目标IP地址和每一条目的子网掩码(Genmask
)进行 与运算,得到结果如果与该条目的 Destination
相同,代表两者相匹配,即使用该网卡。
如果其他所有条目都无法匹配,就会自动匹配默认网关,它目标地址和子网掩码都是 0.0.0.0,
并且后续就把包发给路由器,Gateway
即是路由器的 IP 地址。
四、组装MAC头部
一般在 TCP/IP 通信里,MAC 包头的协议类型只使用:
0800
: IP 协议0806
: ARP 协议
发送方和接收方的MAC地址如何确认?
发送方:MAC 地址是在网卡生产时写入到 ROM 里的,读取出来写入到 MAC 头部就可以了。
接收方:需要 ARP
协议帮我们找到路由器的 MAC 地址。
ARP 协议会在以太网中以广播的形式,对以太网所有的设备喊出:“这个 IP 地址是谁的?请把你的 MAC 地址告诉我”。
然后就会有人回答:“这个 IP 地址是我的,我的 MAC 地址是 XXXX”。
如果对方和自己处于同一个子网中,那么通过上面的操作就可以得到对方的 MAC 地址。然后将这个 MAC 地址写入 MAC 头部,MAC 头部就完成了。
(发包时先查询 ARP 缓存,当 ARP 缓存中不存在对方 MAC 地址时,则发送 ARP 广播查询。)
在 Linux 系统中,我们可以使用 arp -a
命令来查看 ARP 缓存的内容。
到这里就成功的形成了一个网络包,接下来需要进行网络包传输。
网络包只是存放在内存中的一串二进制数字信息,没有办法直接发送给对方。因此需要将数字信息转换为电信号,才能在网线上传输。
负责执行这一操作的是网卡,要控制网卡还需要靠网卡驱动程序。
网卡驱动获取网络包之后,会将其复制到网卡内的缓存区中,接着会在其开头加上报头和起始帧分界符,在末尾加上用于检测错误的帧校验序列。
- 起始帧分界符是一个用来表示包起始位置的标记
- 末尾的
FCS
(帧校验序列)用来检查包传输过程是否有损坏
最后网卡会将包转为电信号,通过网线发送出去。
五、交换机
电信号到达网线接口,交换机里的模块进行接收,接下来交换机里的模块将电信号转换为数字信号。
然后通过包末尾的 FCS
校验错误,如果没问题则放到缓冲区。这部分操作基本和计算机的网卡相同,但交换机的工作方式和网卡不同。
计算机的网卡本身具有 MAC 地址,并通过核对收到的包的接收方 MAC 地址判断是不是发给自己的,如果不是发给自己的则丢弃;相对地,交换机的端口不核对接收方 MAC 地址,而是直接接收所有的包并存放到缓冲区中。因此,和网卡不同,交换机的端口不具有 MAC 地址。
将包存入缓冲区后,接下来需要查询一下这个包的接收方 MAC 地址是否已经在 MAC 地址表中有记录了。
交换机根据 MAC 地址表查找 MAC 地址,然后将信号发送到相应的端口。
当 MAC 地址表找不到指定的 MAC 地址会怎么样?
找不到有两种情况:具有该地址的设备还没有向交换机发送过包。或者这个设备一段时间没有工作导致地址被从地址表中删除了。
交换机就会将包转发到除了源端口之外的所有端口上,无论该设备连接在哪个端口上都能收到这个包。
如果接收方 MAC 地址是一个广播地址,那么交换机会将包发送到除源端口之外的所有端口。
以下两个属于广播地址:
- MAC 地址中的
FF:FF:FF:FF:FF:FF
- IP 地址中的
255.255.255.255
六、路由器
路由器和交换机是有区别的。
路由器是基于 IP 设计的,俗称三层网络设备,各个端口都具有 MAC 地址和 IP 地址;
交换机是基于以太网设计的,俗称二层网络设备,端口不具有 MAC 地址。
首先,电信号到达网线接口部分,路由器中的模块会将电信号转成数字信号,然后通过包末尾的 FCS
进行错误校验。
如果没问题则检查 MAC 头部中的接收方 MAC 地址,看看是不是发给自己的包,如果是就放到接收缓冲区中,否则就丢弃这个包。
MAC 头部的作用就是将包送达路由器,其中的接收方 MAC 地址就是路由器端口的 MAC 地址。因此,当包到达路由器之后,MAC 头部的任务就完成了,于是 MAC 头部就会被丢弃。
接下来,路由器会根据 MAC 头部后方的 IP
头部中的内容进行包的转发操作。转发会查询路由表,同上文的与运算匹配。
我们需要根据路由表的网关列判断对方的地址。
- 如果网关是一个 IP 地址,则这个IP 地址就是我们要转发到的目标地址,还未抵达终点,还需继续需要路由器转发。
- 如果网关为空,则 IP 头部中的接收方 IP 地址就是要转发到的目标地址,也是就终于找到 IP 包头里的目标地址了,说明已抵达终点。
发送后会经过一些交换机和路由器最后到达终点。在此过程中,源 IP 和目标 IP 始终是不会变的,一直变化的是 MAC 地址,因为需要 MAC 地址在以太网内进行两个设备之间的包传输。
数据包抵达了服务器后,服务器开始拆快递
然后把客户端需要的页面封装在 HTTP 响应报文里。
HTTP 响应报文也需要 TCP、IP、MAC 头部,然后由服务端发给客户端。
客户端收到的数据包后同样开始拆包,得到 HTTP 响应报文后,交给浏览器去渲染页面,网页就可以正常显示了。
最后,客户端向服务器发起了 TCP 四次挥手,双方的连接断开。
总结
1.域名解析获得IP地址。
2.HTTP报文通过依次组装TCP头部,IP头部和MAC头部形成网络包。
3.网卡在网络包开头添加报头和起始帧分界符,在网络包末尾添加 FCS
(帧校验序列)。
4.交换机根据 MAC 地址表查找 MAC 地址,然后将信号发送到相应的端口。路由器查询路由表进行转发。(网络包需要经过多个交换机和路由器的转发才能到达目的地)
5.服务器拆包后发送HTTP 响应报文,响应报文组装 TCP、IP、MAC 头部后发给客户端。
6.客户端拆包后渲染页面。