网络,网络...git
虽然只是一个简单的名词,可是她的背后却掩藏着太多太多的故事以及知识。github
穷其编程的一辈子,或许也只能探索出那冰山一角,嗨...web
小时虽知,学海无涯,却绝不知意。玩乃天性,却空流时光。憾...编程
so,矫情之余,咱们来探索一下网络到底是怎么传输的。浏览器
探索网络的范围,都在上图有所展现(另存为看大图)。缓存
打开一个网站,都是从浏览器中输入网址开始,咱们的探索也是从这里开始。安全
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格式看下图。
生成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服务器。
经过DNS服务器查询,咱们已经获得的Web服务器的IP,接下来就要开始发送数据了。而这部分也是比较难写的一部分,由于咱们要深刻协议栈的内部,去了解它的结构。
咱们都知道数据的传输,都是由上层委托给下层工做的。应用程序将发送的信息的行为委派给了操做系统,而操做系统内部就是经过协议栈来工做的。
来看下操做系统协议栈图。
上部分是TCP协议和UDP协议,都是负责数据的收发部分,区别在于TCP是面向链接的,是一种可靠的协议,而UDP只负责发送,不保证准确到达。
下部分是IP协议,负责发送网络包,其中还包括ICMP协议(检查发送过程是否存在错误)和ARP协议(查询MAC地址)。
数据收发
在查询IP地址的时候,咱们用到了Socket库,这里一样也须要用到它。
不过咱们这里须要调用多个组件,才能实现数据的收发,从功能上能够分为四个部分。
建立套接字 (new Socket)
链接服务器的套接字 (connection)
收发数据 (write、read)
删除套接字 (close)
在讲以前,咱们先了解下套接字。
套接字在数据收发中是至关重要的,它是一块内存空间,里面存放着很重要的的控制信息。
这些控制信息存放着通讯对象的IP地址、端口、链接状态、响应时间、数据收发状况等等,只有这些存在,才能知道数据发送到哪里,又发送了多少,有没有错误等等。
建立套接字仍是很是简单的,直接调用Socket库中的socket组件便可,建立完成以后会返回一个标识符,标识符的主要做用就是为了区别不一样的套接字。
链接服务器用到的是connect组件,参数有标识符、服务器的IP、端口等,至关于和服务器之间链接了一条数据管道,后期数据在其中流通。
同时在这里也会发生著名的“三次握手”。
在刚发生链接阶段,管道里面是没有数据的,可是会有控制信息,这些控制信息包括TCP头部,以太网头部、IP头部。
控制信息
根据层级来,咱们会先生成TCP头部,TCP头部格式有不少字段,其中重要的就是双方的端口,序号,ACK号,控制位,窗口等。稍微了解一下这些字段的做用。
端口
端口和IP是一同存在的,在互联网早期的时候,公司联网都是直接用公网IP的,但随着互联网的发展,公网IP愈来愈少,因而就出现了公网和内网的区别。
内网IP范围
10.0.0.0 ~ 10.255.255.255
172.16.0.0 ~ 172.31.255.255
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号,重复以上步骤,直到接收方收到全部数据。
接收方收到所有数据后,一样会向发送方发送数据,下面的步骤都和上面差很少了,这里再也不赘述。
和接收方通讯完成以后,套接字不会再使用,这时就能够删除套接字了。
套接字删除能够由任何一方发起,这里假设服务器端发起,下面就来说讲著名的“四次挥手”。
接收方收到所有数据后,等待一会就会删除套接字。
服务器生成断开信息,即将TCP的头部控制位的FIN设置为1,发送给客户端。
客户端返回ACK号,表示发送的信息无误。
客户端全部数据处理完成后,向服务器发送FIN为1的断开信息。
服务器返回ACK号,表示发送的信息无误,等待一会,客户端和服务器端都删除套接字。
讲到这里,数据收发的绝大数内容就讲完了,接下来咱们聊一聊IP模块。
IP模块
前面提到过,在IP模块会生成IP头部和以太网头部。那么这两个头部究竟有什么做用?
为了便于理解,咱们这里就讲的简单一些。
发送的数据到达子网的集线器或者交换机,经过MAC表,找到下一个转发设备的MAC地址,以“以太网协议”传输到下一个转发设备。
转发设备根据目标地址的IP和“IP协议”判断下一个转发设备的IP,再经过MAC地址,传输到下一个转发设备。
就这样,通过多个转发设备的接力后,网络包最终到达接收方的网络设备。
总结:IP协议根据目标地址判断下一个IP转发设备的位置,再经过以太网协议将网络包输出到下一个转发设备。
其实在到达Web服务器以前,咱们也应该讲讲数字信号是如何转化为电子信号的? 数据又是如何经过运营商到达Web服务器的?
只是这部分实在过于复杂,也多数跟硬件以及运维方向有关,这里就不讲了。
首先,咱们来说一讲Web服务器的部署。
Web服务器的部署有三种方式
直接部署在公司的内网。
公司的内网和Web服务器分开部署。在接入网以后,部署统一防火墙,再分别进去内网和服务器。
web服务器部署在运营商的数据中心。
三种方式自上而下,性能和安全上会愈来愈好,只是管理上可能会麻烦些。
为了安全和分担负载,Web服务器前面会部署防火墙,可能还会有负载均衡器、缓存服务器、内容分发等等。
数据在通过层层过滤后,最终到达Web服务器,服务器的程序和上面建立链接的步骤稍有不一样。
首先是建立套接字(socket)。
绑定套接字和端口号(bind)。
等待链接(listen)。
接受链接(accept)。
服务器的程序会一直等待客户端的链接。
在接收到客户端的请求后,Web服务器根据URI转换为实际的文件名,并做出响应。格式以下。
到这里,咱们全部的内容就到这里了。
最后,祝你们天天身体健康,开心编程,看的开心。嘿...