当我们村里第一次通网

当我们村里第一次通往,当我们的电脑第一次连接上网络,并打开一个网页会触发怎样的事件呢?

 

1.准备阶段:为主机获取一个IP地址

  对于我们大部分家用主机来说第一步便是要连接上路由器,这时候我们的主机是没有IP地址的,没有IP地址什么也干不了,但是我们的主机有一个MAC地址,这是主机的网络接口生产出来便自带的,世界上任何两个网络接口的MAC地址都不一样。

  那要怎样获得一个IP地址呢,这就需要用到DHCP协议(动态主机配置协议)。什么意思呢,就是由DHCP服务器给我们的主机动态的分配一个IP地址,当我们连接到不同的DHCP服务器所获得的IP地址都不一样,也就是说我们主机的IP地址其实是会变的。

    DHCP协议的第一步先由我们的主机操作系统形成一个DHCP请求报文,相当于是想要告诉DHCP服务器我这个主机想要一个IP地址,速速给我拿来。并将这个报文段由应用层发送到传输层,形成一个目的端口为67源端口为68的UDP报文段。为了将UDP报文段继续向下传输到网络层的IP数据报中,需要源IP目的IP,让路由器知道这个数据从哪来到哪去。由于此时我们的主机并没有IP地址,所以使用0.0.0.0作为源IP地址,这是IP协议中所保留的IP地址,代表着当前主机的本地地址。同时我们也不知道目的地在哪,所以目的IP地址也不清楚,所以使用255.255.255.255作为目的IP地址,这是也是IP协议中所保留的IP地址,是一个广播地址,使用这个IP地址,这段数据便会发送给局域网中的所有主机,这些主机中当然也包括DHCP服务器。

  这个包含DHCP请求报文的IP数据报继续向下传输,到达链路层形成一个以太网帧。这个以太网帧有着目的MAC地址,代表着想要传输到哪个网络接口,当然这时候我们还不知道,这时便和在网络层的操作差不多,将目的MAC地址设置为FF:FF:FF:FF:FF:FF,将这个以太网帧发送到与主机相连的交换机所连接的所有其他主机上。与网络层不同的是这时候我们的源MAC地址是知道的,这在我们的主机的网络接口生产出来就自带的,我们假设它是28:45:45:28:6D:5A

  这个以太网帧被发送到局域网内所有的主机上,当然也包括我们的路由器,为什么这时候又说是路由器而不是DHCP服务器了呢,实际上在我们生活中大部分的DHCP服务器都运行在路由器之上。路由器接受到了这个DHCP请求报文形成的以太网帧便相当于DHCP服务器收到了这个以太网帧。路由器便从这个以太网帧中抽出IP数据报到达网络层,发现这个IP数据报的目的IP是广播地址,表明需要继续分解成UDP数据报上传到传输层UDP进行处理,自此这个DHCP请求报文到达了DHCP服务器。

  假设我们的路由器中的DHCP服务器用CIDR进行IP地址的分配(CIDR无类别域间路由,也就是说IP地址不进行分类,32比特的IP地址被分成两个部分a.b.c.d/x,x代表着第一部分的比特数,在这之前的IP都采用分类编址方案,将IP地址分成A,B,C,D四种网络,这样子有很大一部分的IP地址被浪费掉了),假设分配的地址块范围是68. 85. 2. 0/24,分配给我们主机的IP地址是68.85.2.101。DHCP服务器将这个分配给我们的IP地址和子网块(68.85.2.0/24),DNS服务器地址(125.2.23.55),网关地址封装到一个DHCP ACK的数据报中,并依次形成UDP数据报-IP数据报-以太网帧,重新发送到我们的主机上。

    以太网帧在到达交换机时,由于交换机有自学习的功能,我们主机刚刚发送DHCP请求时已经到达过这个交换机,所以交换机记下了我们主机的MAC地址和交换机的哪一个端口相连接,这个以太网帧便能够直接通过交换机到达我们的主机,而不是像第一次那样需要通过广播的方式来传输。

    这个时候,包含DHCP ACK的报文的以太网帧终于抵达了我们的主机,主机从该以太网帧中抽取IP数据报,然后抽取UDP数据报,最后从UDP数据报中抽取出DHCP ACK的报文。我们主机中的DHCP客户根据其中所给的IP,网关地址,DNS服务器地址配置好自己的网络组件,我们的主机最终将向这个网关地址发送数据给目的IP地址为68. 85. 2. 0/24以外所有地址。经过上面这么多的操作,现在我们的主机终于能够处理来自浏览器的web请求了。

 

2.准备阶段:利用DNS服务器解析域名

   这时候我们在浏览器的输入框中输入URL=www.baidu.com,另一项浩大的工程又开始了。我们在浏览器中输入的是一个服务器的域名,但浏览器并不知道这个域名代表的服务器在哪里,我们需要一个IP地址像经纬度定位一个位置那样来定位一个服务器,为了得到这个IP地址,我们需要问问DNS服务器,www.baidu.com的IP地址是多少。为了与百度的服务器建立起连接浏览器创建了一个TCP套接字(对TCP/IP协议的一个封装),这个套接字用于向百度的服务器发送HTTP请求,HTTP协议是建立在TCP协议之上的。当然在这之前为了生成这个套接字这时便需要用到DNS协议。

     首先我们主机的操作系统生成了一个DNS查询报文,将www.baidu.com放在报文的问题段中,之后封装成一个目标端口为53的UDP报文段中。之后继续向下形成一个目标IP地址为125.2.23.55源IP地址为68.85.2.101的IP数据报中。最终在链路层形成一个以太网帧想要发送到DNS服务器。但这个时候还有一个问题,我们并不知道网关路由器的MAC地址,我们只知道DHCP服务器的MAC地址,虽然来说这两个东西的MAC地址实际上是一样的,但我们的主机并不知道,所以这时候又得运用到ARP协议(地址解析协议Address Resolution Protocol),来将我们已知的网关IP地址转化为网关的MAC地址。

    这时候我们的主机生成一个目的IP地址为网关地址的ARP查询报文,然后形成一个目的MAC地址为FF:FF:FF:FF:FF:FF的以太网帧,源MAC地址自然是我们主机网络接口的MAC地址,向局域网内的所有设备进行广播,这其中当然也就包括我们的网关设备。之后网关路由器收到包含ARP查询报文的以太网帧,发现在这个查询报文中的目的IP地址与自己的IP地址相同,于是准备一个ARP回答,告诉目标主机68.85.2.101IP地址(我们主机自己的IP地址)所对应的MAC地址是00:22:6B:45:1F:1B(网关的MAC地址),向交换机发送这个以太网帧,然后发送到我们的主机上,我们的主机抽取出其中的ARP回答报文,最终得到网关的MAC地址。

    经过这么多操作,现在可以向DNS服务器发送一个包含DNS查询报文的以太网帧了。这个以太网帧中的IP数据报的目的IP地址便是125.2.23.55(DNS服务器的地址),目的MAC地址便是刚刚获得的网关MAC地址。这个以太网帧经过交换机到达网关路由器。网关路由器抽取出其中的IP数据报,发现了其中的目的IP地址为125.2.23.55,查询路由器内的转发表然后便将其转发到了电信的路由器中。电信的路由器也接收到了这个DNS查询报文,也抽取IP数据报查询目的IP地址查询自己的转发表,电信路由器的转发表已经由域内协议(如RIP协议和OSPF协议)和因特网的域间协议(BGP)所计算出来。

    经过多次转发之后,这个DNS查询报文终于到达了目的IP地址所指向的DNS服务器。假设这个DNS服务器是一个本地DNS服务器,同时它的缓存中并没有www.baidu.com的服务器IP地址(虽然这也不太可能),这时候他便依次向根DNS服务器,顶级域DNS服务器,权威域DNS服务器发送请求,最终会有权威域DNS服务器包含对应www.baidu.com的IP地址202.108.22.5的源记录,这个权威域DNS服务器生成了一个包含百度域名和IP地址的DNS回答报文发送到本地DNS服务器。本地DNS服务器再利用该报文的UDP报文段形成一个目的IP为我们主机IP的IP数据报中。这个数据报又经由电信的网络发送到我们的路由器上,最终通过交换机到达我们的主机。这时我们的主机便可以提取出其中的DNS回答报文,找到www.baidu.com域名所对应的IP地址,终于可以开始准备与百度的服务器进行连接了。

 

3.通过TCP/IP协议和HTTP协议与服务器交互

    有了www.baidu.com的IP地址,TCP套接字也就能成功的被创建出来。众所周知HTTP协议是运行在TCP协议之上的,那么为了能给百度发送HTTP请求,我们需要进行TCP连接的经典动作——三次握手。我们的主机先生成一个目标端口为80的TCP SYN报文段,在该报文段的首部中设置SYN=1,ACK=0,同时选择一个初始序号seq=i,TCP中规定当SYN字段等于1时报文中不能携带数据,这时我们的主机进入STN-SENT 状态,之后该报文段被放置在一个目的IP地址为202.108.22.5(www.baidu.com的IP地址)的IP数据报中,该数据报又被放置在目的MAC地址为00:22:6B:45:1F:1B(网关的MAC地址)的以太网帧中发送出去,最终这个以太网帧会通过网关路由器和电信服务商的路由器到达www.baidu.com。这便是三次握手中的第一次握手。

   当然在我们的的数据到达百度服务器之前会经过百度的防火墙,在确定我们是一个合法的请求之后才会允许我们的数据进入百度服务器,之后百度服务器从以太网帧中抽出IP数据报抽取TCP SYN报文。这时百度的HTTP服务器和我们主机之间的TCP连接生成一个连接套接字,产生一个TCP SYNACK报文段,在该报文段首部中设置SYN=1,ACK=i+1,也为自己选择一个初始序列号seq=j。这个报文段也会像之前那样逐步到达我们的主机中。操作系统分解出数据报到TCP套接字中,从而进入连接状态。这是第二次握手。

   这时还要向服务端的进程发送确认,确认报文段的ACK=1,确认号ack=j+1,自己的序号为seq=i+1,第三次握手的报文段中可以携带数据,也就是说现在我们可以准备向www.baidu.com发送数据了。我们的浏览器生成了一个要获取URL的HTTP GET报文,这个报文被写入套接字成为但三次握手中TCP报文段的一个载荷,放置进数据报,发送到www.baidu.com。这时TCP连接已经建立起来了,客户端进入ESTABLISH(已建立连接)状态。

    www.baidu.com的HTTP服务器从TCP套接字中取出报文段,这时服务端也进入了ESTABLISH(已建立连接)状态,生成HTTP响应报文,并且将HTTP请求网页的内容放入响应体中,传给TCP套接字。包含响应报文的数据报又经过多重转发,到达我们的主机中,浏览器也从套接字中取出HTTP响应,再从响应体中抽取出html,最终显示在我们的浏览器中,自此一个web请求终于达成了它的使命。

 

posted @   redintonc  阅读(49)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
点击右上角即可分享
微信分享提示