亲宝软件园·资讯

展开

带你探索网络里的那些秘密

SexyPhoenix 人气:2

背景


网络,网络...

虽然只是一个简单的名词,但是她的背后却掩藏着太多太多的故事以及知识。

穷其编程的一生,或许也只能探索出那冰山一角,嗨...

小时虽知,学海无涯,却毫不知意。玩乃天性,却空流时光。憾...

so,矫情之余,我们来探索一下网络究竟是怎么传输的。

概述


探索网络的范围,都在上图有所展示(另存为看大图)。

正文


一. 生成HTTP请求消息

打开一个网站,都是从浏览器中输入网址开始,我们的探索也是从这里开始。

https: 是协议,告诉浏览器我们要访问的目标,而https: 代表的就是访问Web服务器,当然也有其他的协议。比如ftp:访问的就是FTP服务器等。

sexyphoenix.github.io 是Web服务器域名,可以告诉我们在哪里可以找到Web服务器。

about/ 是Web服务器里面的文件路径名,这里的about是目录名,全路径可能是about/index.md,而index.md应该被github掩藏了。

浏览器首先要做的就是对URL进行解析,知道我们要访问的是sexyphoenix.github.io这个Web服务器上文件路径为about目录下的默认文件。

知道了要访问的目标,接下来浏览器就要生成HTTP的请求信息,介绍到这,就要聊一聊HTTP协议了。

HTTP协议规定了客户端和服务器通信的内容和步骤,简单来说,就是两个部分“对什么”做“怎样的操作”。

“对什么”上面已经解析过了,“怎样的操作”就是HTTP主要的方法:POST、GET、DELETE、PUT等。HTTP格式看下图。

二、查询Web服务器的IP地址

生成HTTP信息之后,接下来,我们就要发送信息给Web服务器了。但此时我们突然发现我们只有Web服务器的域名,并不知道服务器究竟在哪里。

那么我们应该如何像现实中送快递一样,快速的定位到哪一幢哪一室,讲到这里,想必大家都有所意会了,IP。

IP地址

IP地址实际就是4个字节,32比特的数字,每8个比特为1组,具体看下图十进制表示。

我们发送的信息,就是通过子网的集成器找到最近的路由器,再通过路由器(基于IP设计)找到最优抵达Web服务器的路由器,这样不断的查找网络中的路由器节点,最终抵达Web服务器。

注意,我们的Web服务器的IP是最终的目的地,它是贯穿路由器---N---路由器---Web服务器整个环节的,是判断整个网络走向的依据,存在控制信息中。

路由器都有自己的IP,路由器到路由器就是根据Web服务器的IP(走向),通过本身的IP来移动。

到这里,我们也就了解清楚了通过IP,发送的信息最终可以抵达Web服务器。

那么,我们现在的问题就是如何通过Web服务器的域名找到它的IP? 讲到这里,想必大家又都有所意会了,DNS。

域名解析

简单的来说,DNS服务器维持了一系列关系表,也就是域名和IP对于的关系表。浏览器向最近的DNS服务器询问“sexyphoenix.github.io”的IP地址是多少,DNS服务器会回答Web服务器IP为xxx。这一步也叫域名解析

讲到这里,我们就要深究一下,浏览器究竟是怎样向DNS服务器发送查询的?

首先,我们要清楚一点,浏览器等应用程序本身是不能发送信息的,而是委托给操作系统来发送的。

而操作系统有一个超级出名的库,Socket库,它是调用网络功能的程序组件集合。

Socket库里面有一个函数。

IP信息 = gethostbyname("sexyphoenix.github.io") # 看,应用程序查询IP很简单,调用一个函数即可

发送数据有两种协议,UDP和TCP,域名查询用的是UDP。数据短速度快。

介绍了域名解析,下面来了解一下DNS服务器的工作。

DNS服务器

在上面已经提到过了,DNS服务器维护了一个关系表,上图的类型A表示域名对应IP地址,MX表示域名对应的邮箱服务器,不同的类型,返回的信息有所不同。

DNS服务器的工作就是根据域名和类型,查找相关的记录,并向应用程序返回响应信息。

DNS服务器查找

全球共有13台根域名服务器,根域名用“.”表示,其次才是下面的一级域名“com.”、“net.”等,我们平时访问的域名“sexyphoenix.github.io.”后面有一个点,平时被省略。

我们用一张图来看下查找顺序,更清楚些。

先找最近的DNS服务器(一般是本机设置的),没有再从根域找,然后不断的向下找,直到找到我们Web服务器IP所在的DNS服务器。

三、TCP/IP传输数据

通过DNS服务器查询,我们已经得到的Web服务器的IP,接下来就要开始发送数据了。而这部分也是比较难写的一部分,因为我们要深入协议栈的内部,去了解它的结构。

我们都知道数据的传输,都是由上层委托给下层工作的。应用程序将发送的信息的行为委派给了操作系统,而操作系统内部就是通过协议栈来工作的。

来看下操作系统协议栈图。

上部分是TCP协议和UDP协议,都是负责数据的收发部分,区别在于TCP是面向连接的,是一种可靠的协议,而UDP只负责发送,不保证准确到达。

下部分是IP协议,负责发送网络包,其中还包括ICMP协议(检查发送过程是否存在错误)和ARP协议(查询MAC地址)。

数据收发

在查询IP地址的时候,我们用到了Socket库,这里同样也需要用到它。

不过我们这里需要调用多个组件,才能实现数据的收发,从功能上可以分为四个部分。

  1. 创建套接字 (new Socket)

  2. 连接服务器的套接字 (connection)

  3. 收发数据 (write、read)

  4. 删除套接字 (close)

在讲之前,我们先了解下套接字。

套接字在数据收发中是相当重要的,它是一块内存空间,里面存放着很重要的的控制信息。

这些控制信息存放着通信对象的IP地址、端口、连接状态、响应时间、数据收发情况等等,只有这些存在,才能知道数据发送到哪里,又发送了多少,有没有错误等等。

创建套接字

创建套接字还是非常简单的,直接调用Socket库中的socket组件即可,创建完成之后会返回一个标识符,标识符的主要作用就是为了区别不同的套接字。

连接服务器的套接字

连接服务器用到的是connect组件,参数有标识符、服务器的IP、端口等,相当于和服务器之间连接了一条数据管道,后期数据在其中流通。

同时在这里也会发生著名的“三次握手”。

在刚发生连接阶段,管道里面是没有数据的,但是会有控制信息,这些控制信息包括TCP头部,以太网头部、IP头部。

控制信息

根据层级来,我们会先生成TCP头部,TCP头部格式有很多字段,其中重要的就是双方的端口,序号,ACK号,控制位,窗口等。稍微了解一下这些字段的作用。

端口

端口和IP是一同存在的,在互联网早期的时候,公司联网都是直接用公网IP的,但随着互联网的发展,公网IP越来越少,于是就出现了公网和内网的区别。

内网IP范围

  1. 10.0.0.0 ~ 10.255.255.255

  2. 172.16.0.0 ~ 172.31.255.255

  3. 192.168.0.0 ~ 192.168.255.255

每个公司的内部都使用这些内网IP,再通过唯一的一个公网IP访问互联网,这样就可以节省大量的公网IP。

那么公司的这些设置内网IP的电脑是如何通过唯一的公网IP访问互联网呢? 互联网返回的信息又是怎么通过唯一的公网IP,定位到公司的某一台电脑上的?

地址转换(NAT),这个技术就解决了上面的问题,它的原理就是在转发网络包时对IP头部地址和端口进行改写。

而端口在其中的作用至关重要,它可以让路由器(公网IP)知道是那一台内网的电脑与互联网通信,具体看下图。

公司IP为192.168.23.183的电脑,通过49158端口向互联网发送连接,当到达公司的公网路由器的时候,路由器的IP模块会对控制信息进行改写,最后变成IP为121.225.19.59,端口为1001和通信对象通信。

同时将这条记录保存在路由器上,当通信对象返回信息时,会通过表格中的信息找到对应的内网电脑IP。

序号

发送方告诉接收方该网络包在所有发送的数据的第几个字节,序号的初始值是在连接阶段随机生成的(防止攻击者猜到),在下面的收发数据阶段,就是以这个序号为基数。

ACK号

接收方告诉发送发已经收到所有数据的第几个字节,相当于序号+发送的数据长度。

控制位

每一个比特代表不同的控制信息,看下图。

图中解释了比较重要的控制位。

窗口

接收方告诉发送方的窗口大小,如果接收方接受的速度比较慢,一起传送的数据量就会变小相当于控制了我们传送数据的快慢。

介绍了TCP头部的关键字段,接下来我们开始进入连接。

首先,我们会将客户端的控制位的SYN(1)、生成随机序号M、窗口大小等,再通过其他层,到达服务器端(第一次握手)。

服务器收到SYN为1的信息,知道客户端要和我连接,生成ACK号(M+1)、服务器随机序号N(通信是双向的,这时的服务器也相当于发送方)、控制位SYN(1)、窗口等发送(第二次握手)。

客户端收到服务器端的信息,得到ACK号,知道连接正常,发送ACK号(N+1,服务器端的序号)、控制位SYN(1),告诉服务器已建立连接(第三次握手)。

收发数据

管道连接建立成功后,就进入了数据收发阶段。

我们发送的信息一般都是比较大的,不可能一次性发送完毕,所以在TCP模块,就会将应用数据切分成数据块,切分的每个数据块(MSS,最大数据长度)加上TCP头部,IP头部不能超过MTU大小(MTU,最大传输单元)。

接下来,交给IP模块,生成IP头部和MAC头部信息,再通过网卡驱动,网卡设备将数字信息转变成电信号,传输到接收方。接收方收到信息,会返回ACK号,重复以上步骤,直到接收方收到所有数据。

接收方收到全部数据后,同样会向发送方发送数据,下面的步骤都和上面差不多了,这里不再赘述。

删除套接字

和接收方通信完成之后,套接字不会再使用,这时就可以删除套接字了。

套接字删除可以由任何一方发起,这里假设接受方发起,下面就来讲讲著名的“四次挥手”。

接收方收到全部数据后,等待一会就会删除套接字。

  1. 接收方生成断开信息,即将TCP的头部控制位的FIN设置为1,发送给客户端。

  2. 客户端返回ACK号,表示发送的信息无误。

  3. 客户端所有数据处理完成后,向服务器发送FIN为1的断开信息。

  4. 服务器返回ACK号,表示发送的信息无误,等待一会,发送方和接收方都删除套接字。

讲到这里,数据收发的绝大数内容就讲完了,接下来我们聊一聊IP模块。

IP模块

前面提到过,在IP模块会生成IP头部和以太网头部。那么这两个头部究竟有什么作用?

为了便于理解,我们这里就讲的简单一些。

发送的数据到达子网的集线器或者交换机,通过MAC表,找到下一个转发设备的MAC地址,以“以太网协议”传输到下一个转发设备。

转发设备根据目标地址的IP和“IP协议”判断下一个转发设备的IP,再通过MAC地址,传输到下一个转发设备。

就这样,经过多个转发设备的接力后,网络包最终到达接收方的网络设备。

总结:IP协议根据目标地址判断一下个IP转发设备的位置,再通过以太网协议将网络包输出到下一个转发设备。

四、到达Web服务器

其实在到达Web服务器之前,我们也应该讲讲数字信号是如何转化为电子信号的? 数据又是如何通过运营商到达Web服务器的?

只是这部分实在过于复杂,也多数跟硬件以及运维方向有关,这里就不讲了。

首先,我们来讲一讲Web服务器的部署。

Web服务器的部署有三种方式

  1. 直接部署在公司的内网。

  2. 公司的内网和Web服务器分开部署。在接入网之后,部署统一防火墙,再分别进去内网和服务器。

  3. web服务器部署在运营商的数据中心。

三种方式自上而下,性能和安全上会越来越好,只是管理上可能会麻烦些。

为了安全和分担负载,Web服务器前面会部署防火墙,可能还会有负载均衡器、缓存服务器、内容分发等等。

数据在经过层层过滤后,最终到达Web服务器,服务器的程序和上面创建连接的步骤稍有不同。

  1. 首先是创建套接字(socket)。

  2. 绑定套接字和端口号(bind)。

  3. 等待连接(listen)。

  4. 接受连接(accept)。

服务器的程序会一直等待客户端的连接。

在接收到客户端的请求后,Web服务器根据URI转换为实际的文件名,并作出响应。格式如下。

到这里,我们所有的内容就到这里了。

最后,祝大家每天身体健康,开心编程,看的开心。嘿...

加载全部内容

相关教程
猜你喜欢
用户评论