网络是怎么连接的
探索之旅路线图
(1)浏览器向Web服务器发送请求。
(2)Web服务器根据请求向浏览器发送响应。
浏览器和Web服务器之间传递请求和响应的机制:
由操作系统中的网络控制软件,以及交换机、路由器等设备分工合作来实现的,它的基本思路是将数字信息分割成一个一个的小块,然后装入一些被称为“包”(Packet)的容器中来运送。“包”这个词大家可能在用手机的时候经常会碰到,但在这里类似于邮政和快递中的概念。大家可以这样理解:**包相当于信件或者包裹,而交换机和路由器则相当于邮局或快递公司的分拣处理区。包的头部存有目的地等控制信息,通过许多交换机和路由器的接力,就可以根据控制信息对这些包进行分拣,然后将它们一步一步地搬运到目的地。**无论是家庭和公司里的局域网,还是外面的互联网,它们只是在规模上有所不同,基本的机制都是相同的。
- 第1章Web浏览器
根据一定的规则来解析URL的含义,生成请求信息发送给Web服务器(委托操作系统中的网络控制软件)
- 第2章协议栈、网卡
协议栈(网络控制软件):将浏览器收到的消息打包加上目的地址等控制信息
。
如果拿邮局来比喻,就是把信装进信封,然后在信封上写上收信人的地址。这个软件还有其他一些功能,例如当发生通信错误时重新发送包,或者调节数据发送的速率等,或许我们可以把它当作一位帮我们寄信的小秘书。
协议栈会将包交给网卡(负责以太网或无线网络通信的硬件),网卡会将包转换为电信号并通过网线发送出去。这样一来,包就进入到网络之中了。
- 第3章集线器、交换机、路由器
网卡发送的包会经过交换机等设备,到达用来接入互联网的路由器。路由器的后面就是互联网,网络运营商会负责将包送到目的地,就好像我们把信投到邮筒中之后,邮递员会负责把信送给收件人一样。
- 第4章接入网、网络运营商
接入网:互联网的入口线路
接入点:接入网连接到签约的网络运营商,并接入被称为接入点(Point of Presence, PoP)的设备。
接入点的实体是一台专为运营商设计的路由器,我们可以把它理解为离你家最近的邮局。从各个邮筒中收集来的信件会在邮局进行分拣,然后被送往全国甚至全世界,互联网也是一样,网络包首先通过接入网被发送到接入点,然后再从这里被发送到全国甚至全世界。接入点的后面就是互联网的骨干部分了。
在骨干网中存在很多运营商和大量的路由器,这些路由器相互连接,组成一张巨大的网,而我们的网络包就在其中经过若干路由器的接力,最终被发送到目标Web服务器上。
- 第5章防火墙、缓存服务器
网络包最终到达了Web服务器所在的局域网中。接着,它会遇到防火墙,防火墙会对进入的包进行检查。大家可以把防火墙想象成门口的保安,他会检查所有进入的包,看看有没有危险的包混在里面。检查完之后,网络包接下来可能还会遇到缓存服务器。网页数据中有一部分是可以重复利用的,这些可以重复利用的数据就被保存在缓存服务器中。如果要访问的网页数据正好在缓存服务器中能够找到,那么就可以不用劳烦Web服务器,直接从缓存服务器读出数据。
第1章 浏览器生成消息——探索浏览器内部
1.1 生成HTTP请求消息
1.1.1 输入网址
URL的种类以及组成
1.1.2 浏览器解析URL生成请求信息
1.1.3 省略文件名的情况
http://www.lab.glasscom.com/dir/
在服务器上事先设置好该情况下访问的默认文件名,大多数情况下是index.html或者default.htm之类的文件名。
http://www.lab.glasscom.com/
这个URL也是以“/”结尾的,也就是说它表示访问一个名叫“/”的目录(根目录)。而且,由于省略了文件名,所以结果就是访问/index.html或者/default.htm这样的文件了。
http://www.lab.glasscom.com
当没有路径名时,就代表访问根目录下事先设置的默认文件,也就是/index. html或者/default.htm这些文件,这样就不会发生混乱了。
http://www.lab.glasscom.com/whatisthis
如果Web服务器上存在名为whatisthis的文件,则将whatisthis作为文件名来处理;如果存在名为whatisthis的目录,则将whatisthis作为目录名来处理。
1.1.4 HTTP的基本思路
1.1.5 生成HTTP请求消息
表单中对方法的区分
- 消息行:末尾HTTP的版本号
- 消息头:存放额外的详细信息,如日期、客户端支持的数据类型、语言、压缩格式、客户端和服务器的软件名称和版本、数据有效期和最后更新时间等。
- 消息体:消息的主体。GET方法没有,POST有
1.1.6 发送请求后会收到响应
响应消息的格式以及基本思路和请求消息是相同的,差别只在第一行上。在响应消息中,第一行的内容为状态码和响应短语,用来表示请求的执行结果是成功还是出错。状态码和响应短语表示的内容一致,但它们的用途不同。状态码是一个数字,它主要用来向程序告知执行的结果;相对地,响应短语则是一段文字,用来向人们告知执行的结果。
1.2 向DNS服务器查询Web服务器的IP地址
1.2.1 IP地址的基本知识
子网:通过集线器连接起来的所有计算机。
网络:将子网通过路由器连接起来
IP地址:网络号+主机号
发送端的消息先经过子网的集线器转发到最近的路由器,路由器根据消息的目的判断下一跳(下一个路由器的位置),最后再次经过子网的集线器被转发到下一个路由器。重复该过程,直到到达目的地。
子网掩码:1表示网络号,0表示主机号
IP地址的主机号
全0:表示整个子网
全1:表示向子网上所有设备发送包,即“广播”
1.2.2 域名和IP地址并用的理由
域名容易记忆,IP地址长度32bit(4Byte),域名长度较大增加了路由器的负担,传输数据会花费更长的时间。
DNS:让人来使用名称,让路由器来使用IP地址。为了填补两者之间的障碍,需要有一个机制能够通过名称来查询IP地址,或者通过IP地址来查询名称,这样就能够在人和机器双方都不做出牺牲的前提下完美地解决问题。
1.2.3 Socket库提供查询IP地址的功能
DNS解析器向DNS服务端发送查询消息,并接收服务器返回的响应消息。
计算机有DNS客户端,又称DNS解析器,本质是一段程序,包含在操作系统的Socket库(网络开发中的一种标准库,具有调用网络功能,如发送,接收数据)中。
1.2.4 通过解析器向DNS服务器发出查询
1.2.5 解析器的内部原理
调用解析器时计算机内部的工作流程
DNS服务器地址的设置
1.3 全世界DNS服务器的大接力
1.3.1 DNS服务器的基本工作
来自客户端的查询信息有域名、Class的值永远是代表互联网的IN、记录类型(A:IP地址;MX:邮件服务器);
DNS服务器上事先保存有前面这3种信息对应的记录数据。DNS服务器就是根据这些记录查找符合查询请求的内容并对客户端作出响应的。
1.3.2 域名的层次结构
信息分布式的存放在多台DNS服务器。
DNS中的域名都是用句点来分隔的,比如www.lab.glasscom.com,这里的句点代表了不同层次之间的界限,就相当于公司里面的组织结构不用部、科之类的名称来划分,只是用句点来分隔而已[插图]。在域名中,越靠右的位置表示其层级越高,比如www.lab.glasscom.com这个域名如果按照公司里的组织结构来说,大概就是“com事业集团glasscom部lab科的www”这样。其中,相当于一个层级的部分称为域。因此,com域的下一层是glasscom域,再下一层是lab域,再下面才是www这个名字。
这里先假设一台DNS服务器中只存放一个域的信息,DNS服务器也具有了像域名一样的层次结构,每个域的信息都存放在相应层级的DNS服务器中。例如,这里有一个公司的域,那么就相应地有一台DNS服务器,其中存放了公司中所有Web服务器和邮件服务器的信息。
1.3.3 寻找相应的DNS服务器并获取IP地址
所有的DNS服务器会保存根域服务器。
1.3.4 通过缓存加快DNS服务器的响应
真实的互联网中,一台DNS服务器可以管理多个域的信息。
缓存记录查询过的域名的信息(包括不存在)。缓存保存的信息具有有效期,响应的结果会标记来源于缓存查询。
1.4 委托协议栈发送消息
1.4.1 数据收发操作概览
向操作系统内部的协议栈发出委托时,需要按照指定的顺序来调用Socket库中的程序组件。
套接字 :管道两端的数据出入口
管道:套接字连接起来
收发数据的操作:
(1)创建套接字(创建套接字阶段)服务器启动程序创建套接字等待客户端连接
(2)将管道连接到服务器端的套接字上(连接阶段)
(3)收发数据(通信阶段)
(4)断开管道并删除套接字(断开阶段)
1.4.2 创建套接字阶段
1.4.3 连接阶段:把管道接上去
描述符:应用程序用来识别套接字的机制
IP地址和端口号:客户端和服务器之间用来识别对方套接字的机制(Web是80号端口,电子邮件是25号端口)
客户端在创建套接字时,协议栈会为这个套接字随便分配一个端口号。接下来,当协议栈执行连接操作时,会将这个随便分配的端口号通知给服务器。
1.4.4 通信阶段:传递消息
- 客户端在内存中准备请求消息
- 调用write,指定描述符和发送数据
- 服务器接收数据响应信息
- 客户端调用read,接收数据存放接收缓冲区
1.4.5 断开阶段:收发数据结束
Web使用的HTTP协议规定,当Web服务器发送完响应消息之后,应该主动执行断开操作,因此Web服务器会首先调用close来断开连接。断开操作传达到客户端之后,客户端的套接字也会进入断开阶段。接下来,当浏览器调用read执行接收数据操作时,read会告知浏览器收发数据操作已结束,连接已经断开。浏览器得知后,也会调用close进入断开阶段。
HTTP协议将HTML文档和图片都作为单独的对象来处理,每获取一次数据,就要执行一次连接、发送请求消息、接收响应消息、断开的过程。因此,如果一个网页中包含很多张图片,就必须重复进行很多次连接、收发数据、断开的操作。对于同一台服务器来说,重复连接和断开显然是效率很低的,因此后来人们又设计出了能够在一次连接中收发多个请求和响应的方法。在HTTP版本1.1中就可以使用这种方法,在这种情况下,当所有数据都请求完成后,浏览器会主动触发断开连接的操作。
第2章 用电信号传输TCP/IP数据——探索协议栈和网卡
2.1 创建套接字
2.1.1 协议栈的内部结构
浏览器、邮件等一般应用程序收发数据时用TCP;DNS查询等收发较短的控制数据时用UDP。
下面一半是用IP协议控制网络包收发操作的部分。在互联网上传送数据时,数据会被切分成一个一个的网络包[插图],而将网络包发送给通信对象的操作就是由IP来负责的。
- ICMP:用于告知网络包传送过程中产生的错误以及各种控制消息
- ARP:用于根据IP地址查询相应的以太网MAC地址
IP下面的网卡驱动程序负责控制网卡硬件,而最下面的网卡则负责完成实际的收发操作,也就是对网线中的信号执行发送和接收的操作。
2.1.2 套接字的实体就是通信控制信息
套接字:协议栈内部有一块用于存放控制信息的内存空间,这里记录了用于控制通信操作的控制信息,例如通信对象的IP地址、端口号、通信操作的进行状态等。根据这些消息判断是否要进行重发操作和下一步行动。
套接字就只是一个概念而已,并不存在实体,如果一定要赋予它一个实体,我们可以说这些控制信息就是套接字的实体,或者说存放控制信息的内存空间就是套接字的实体。
2.1.3 调用socket时的操作
调用socket申请创建套接字时,首先分配一个套接字所需的内存空间,然后向其中写入初始状态。
描述符相当于用来区分协议栈中的多个套接字的号码牌。
2.2 连接服务器
2.2.1 连接是什么意思
连接实际上是通信双方交换控制信息,在套接字中记录这些必要信息并准备数据收发的一连串操作:连接实际上是通信双方交换控制信息,在套接字中记录这些必要信息并准备数据收发的一连串操作
连接实际上是通信双方交换控制信息,在套接字中记录这些必要信息并准备数据收发的一连串操作
2.2.2 负责保存控制信息的头部
通信操作中使用的控制信息分为两类。
(1)头部中记录的信息(2)套接字(协议栈中的内存空间)中记录的信息
- 第一类:客户端与服务器相互联络时交换的控制信息。整个通信过程都需要。这些控制信息位于网络包的开头,因此被称为头部。此外,以太网和IP协议也有自己的控制信息,这些信息也叫头部,为了避免各种不同的头部发生混淆,我们一般会记作TCP头部、以太网头部[插图]、IP头部。
- 第二类:保存在套接字中,用来控制协议栈操作的信息。因为协议栈中的控制信息通信对方是看不见的,只要在通信时按照规则将必要的信息写入头部,客户端和服务器之间的通信就能够得以成立。
不同系统的协议栈不同,但可以用命令来显示一些重要的套接字控制信息,这些信息无论何种操作系统的协议栈都是共通的。
2.2.3 连接操作的实际过程
- 应用程序调用Socket库中的connect
- 根据提供的服务器IP和端口组件TCP模块于服务器进行交互
- 客户端创建收发操作的控制信息的头部
- 客户端的套接字找到服务器的套接字
- 服务器响应TCP模块给客户端:将SYN设置为1,表示正在连接状态,ACK设置为1,表示收到消息
- 相应地,客户端收到消息后:根据SYN更新连接的状态(连接完毕)也要ACK设置为1发送给服务器
- 连接成功,直到调用close
2.3 收发数据
2.3.1 将HTTP请求消息交给协议栈
协议栈并不是一收到数据就马上发送出去,而是会将数据存放在内部的发送缓冲区中,并等待应用程序的下一段数据。
MTU:一个网络包的最大长度,以太网中一般为1500字节。
MSS:除去头部之后,一个网络包所能容纳的TCP数据的最大长度。
SFD:Start Frame Delimiter, 起始帧分界符
FCS :Frame Check Sequence,帧校验序列
定时器:当经过一定时间之后,即使缓冲区中的数据长度没有到达MSS,也会把网络包发送出去
应用程序在发送数据时可以指定一些选项,比如如果指定“不等待填满缓冲区直接发送”,则协议栈就会按照要求直接发送数据。像浏览器这种会话型的应用程序在向服务器发送数据时,等待填满缓冲区导致延迟会产生很大影响,因此一般会使用直接发送的选项。
2.3.2 对较大的数据进行拆分
2.3.3 使用ACK号确认网络包已收到
接收端通过片偏移量和数据长度检查收到的网络包有没有遗漏
在建立连接过程中,发送消息给服务端将SYN控制位设为1的同时,还需要同时设置序号字段的值,而这里的值就代表序号的初始值。序号从1开始容易被利用攻击,初值值要随机生成。
数据双向传输时的情况:
数据双向传输时的情况:
- 连接
- 客户端计算序号初始值发送服务器
- 服务器通过初始值计算ACK号返回给客户端
- 服务器也需计算序号初始值发送客户端
- 客户端通过初始值计算ACK号返回服务器
- 数据收发
- 发送端发送数据+序号
- 接收端返回ACK号
- TCP采用数据保存在发送缓冲区,做好重发的准备的补救措施
2.3.4 根据网络包平均往返时间调整ACK号等待时间
TCP采用动态跳转等待时间,避免重发网络包导致或加剧网络拥塞的情况
2.3.5 使用窗口有效管理ACK号
一来一回方式和滑动窗口方式:
滑动窗口与接收缓冲区
在这张图中,接收方将数据暂存到接收缓冲区中并执行接收操作。当接收操作完成后,接收缓冲区中的空间会被释放出来,也就可以接收更多的数据了,这时接收方会通过TCP头部中的窗口字段将自己能接收的数据量告知发送方。
实际上,接收方在收到数据之后马上就会开始进行处理,如果接收方的性能高,处理速度比包的到达速率还快,缓冲区马上就会被清空,并通过窗口字段告知发送方。
2.3.6 ACK与窗口的合并
当接收方将数据传递给应用程序,导致接收缓冲区剩余容量增加时,就需要告知发送方,这就是更新窗口大小的时机。
- 在等待发送ACK号的时候正好需要更新窗口,这时就可以把ACK号和窗口更新放在一个包里发送,从而减少包的数量。
- 当需要连续发送多个ACK号时,也可以减少包的数量,这是因为ACK号表示的是已收到的数据量,也就是说,它是告诉发送方目前已接收的数据的最后位置在哪里,因此当需要连续发送ACK号时,只要发送最后一个ACK号就可以了,中间的可以全部省略。
- 当需要连续发送多个窗口更新时也可以减少包的数量,因为连续发生窗口更新说明应用程序连续请求了数据,接收缓冲区的剩余空间连续增加。
2.3.7 接收HTTP响应消息
- 浏览器在委托协议栈发送请求消息之后,会调用read程序来获取响应消息
- 控制流程会通过read转移到协议栈,然后协议栈会执行接下来的操作
- 接收数据也需要将数据暂存到接收缓冲区中
- 协议栈会将应用程序的委托,也就是从接收缓冲区中取出数据并传递给应用程序的工作暂时挂起,等服务器返回的响应消息到达之后再继续执行接收操作。
协议栈接收数据的具体操作过程
- 协议栈会检查收到的数据块和TCP头部的内容,判断是否有数据丢失,如果没有问题则返回ACK号
- 协议栈将数据块暂存到接收缓冲区中,并将数据块按顺序连接起来还原出原始的数据,最后将数据交给应用程序
- 协议栈会将接收到的数据复制到应用程序指定的内存地址中,然后将控制流程交回应用程序
- 将数据交给应用程序之后,协议栈还需要找到合适的时机向发送方发送窗口更新(合并ACK号和窗口更新)
2.4 从服务器断开并删除套接字
2.4.1 数据发送完毕后断开连接
- 发送端调用Socket库的close程序
- 协议栈生成含有断开信息的TCP头部,具体来说是将控制位中的FIN比特设置为1
- 套接字记录断开操作的相关消息
- 接收端接收到消息后更新套接字的状态:断开操作
- 同时向发送端返回ACK号
- 应用程序调用read读取数据
2.4.2 删除套接字
防止误操作套接字延迟删除
(1)客户端发送FIN(2)服务器返回ACK号(3)服务器发送FIN(4)客户端返回ACK号
若(4)没有收到,删除套接字,重发(3),别的应用程序创建套接字分配到同一个端口号,使得发送到的FIN错误到达新的套接字里面,执行断开。
协议中对于这个等待时间没有明确的规定,一般来说会等待几分钟之后再删除套接字。
2.4.3 数据收发操作小结
2.5 IP与以太网的包收发操作
2.5.1 包的基本知识
TCP模块在执行连接、收发、断开等各阶段操作时,都需要委托IP模块将数据封装成包发送给通信对象
网络包的结构:
发送方、接收方和转发设备:
(1)路由器根据目标地址判断下一个路由器的位置,IP协议根据目标地址判断下一个IP转发设备的位置
(2) 集线器在子网中将网络包传输到下一个路由,子网中的以太网协议将包传输到下一个转发设备
集线器是按照以太网规则传输包的设备,而路由器是按照IP规则传输包的设备
2.5.2 包收发操作概览
- TCP模块委托IP模块发送包,将TCP头部和数据部分一起作为数据部分传递给IP模块
- IP模块添加IP头部(根据IP地址发送目的地的控制信息)和MAC头部(通过以太网的局域网将包传输至最近的路由器所需的控制信息)
- 封装号的包会交给网络硬件(统称网卡),将数字信息转换为电路信号或光信号,并通过网线(或光纤)发送出去,信号通过集线器、路由器等转发设备,在由转发设备一步一步地送达接受方
- 接收方接收包后做出响应,信息以电信号形式传输,由网卡将其转换为数字信息传递给IP模块,IP模块再将TCP头部和数据块传递给TCP模块
无论要收发的包是控制包还是数据包,IP对各种类型的包的收发操作都是相同的。
2.5.3 生成包含接收方IP地址的IP头部
IP头部格式:
IP头部的“接收方IP地址”填写通信对象的IP地址。
发送方IP地址需要判断发送所使用的网卡,并填写该网卡的IP地址。
2.5.4 生成以太网用的MAC头部
在IP中,协议号表示IP头部后面的包内容的类型;而在以太网中,我们可以认为以太网类型后面就是以太网包的内容,而以太类型就表示后面内容的类型。以太网包的内容可以是IP、ARP等协议的包,它们都有对应的值,这也是根据规则来确定的
IP模块根据路由表Gateway栏的内容判断应该把包发送给谁。
设置发送方IP地址时,我们已经判断出了从哪块网卡发送这个包,那么现在只要将这块网卡对应的MAC地址填进去就好了。
我们还需要执行根据IP地址查询MAC地址的操作。
2.5.5 通过ARP查询目标路由器的MAC地址
我们会将查询结果放到一块叫作ARP缓存的内存空间中留着以后用。也就是说,在发送包时,先查询一下ARP缓存,如果其中已经保存了对方的MAC地址,就不需要发送ARP查询,直接使用ARP缓存中的地址,而当ARP缓存中不存在对方MAC地址时,则发送ARP查询
ARP缓存会定时删除(目的是更新当IP地址发生变化的MAC地址变化),再次ARP查询,但是实际更新的速度较慢,可能会发生通信的异常
将MAC头部加在IP头部的前面,整个包就完成了。到这里为止,整个打包的工作是由IP模块负责的,网卡只负责接收,发送的操作,网卡能够灵活支持各种类型的包
2.5.6 以太网的基本知识
2.5.7 将IP包转换成电或光信号发送出去
- 网卡驱动程序初始化,如错误检查、初始设置
- 网卡的ROM中保存世界唯一的MAC地址
- MAC模块获取ROM中的MAC地址
网卡的ROM中保存着全世界唯一的MAC地址,这是在生产网卡时写入的。
网卡中保存的MAC地址会由网卡驱动程序读取并分配给MAC模块。
2.5.8 给网络包再加3个控制数据
- MAC模块会将包从缓冲区中取出,并在开头加上报头和起始帧分界符,在末尾加上用于检测错误的帧校验序列
- 每个包的前面都有报头和起始帧分界符(SFD),报头用来测定时机,SFD用来确定帧的起始位置。
- 合适的编码可以让接收方来同步电信号
- 在包传输过程中,如果受到噪声的干扰而导致其中的数据发生了变化,那么接收方计算出的FCS(帧校验序列)和发送方计算出的FCS就会不同,这样我们就可以判断出数据有没有错误。