《网络是怎样连接的》-----户根勤,读书笔记

1. 浏览器生成消息

1.1 生成HTTP请求消息

  • DNS是一个分布式数据库系统,可以将域名和IP地址映射。在互联网上域名与IP地址之间是一一对应的,域名方便记忆,IP地址被机器识别。两者之间的转换称为域名解析。DNS查询有两种方式:递归迭代。DNS客户端一般都是递归,而DNS服务器之间一般采用迭代查询方式。

  • QQ是直接使用IP地址来连接服务器的,所以即便DNS失效,它依然可以“屹立不倒。

  • 浏览器是一个具备多种客户端功能的综合性客户端软件,因此它需要一些东西来判断应该使用其中哪种功能来访问相应的数据,而各种不同的URL就是用来干这个的,比如访问Web服务器时用“http:”,而访问FTP服务器时用“ftp:”。尽管URL有各种不同的写法,但它们有一个共同点,那就是URL开头的文字,即“http:”“ftp:”“file:”“mailto:”这部分文字都表示浏览器应当使用的访问方法。

  • 协议是一种规则,与是否使用网络无关。

  • HTTP消息的格式:
    在这里插入图片描述

  • get提交通过URL,实际上URL不存在参数上限的问题,http协议没有对URL长度进行限制,URL的限制是特定的浏览器以及服务器的限制;理论上post提交数据大小也是没有限制的,起限制作用的是服务器的处理能力

  • HTTP中主要的头字段:

在这里插入图片描述                ○:在规格中定义的项目。
               △:并非正式规格,而是在规格书附录(Appendix)中定义的附加功能。

  • HTTP状态码:

在这里插入图片描述

  • 由于每条请求消息中只能写1个URI,所以每次只能获取1个文件,如果需要获取多个文件,必须对每个文件单独发送1条请求。比如1个网页中包含3张图片,那么获取网页加上获取图片,一共需要向Web服务器发送4条请求。
  • 尽管浏览器能够解析网址并生成HTTP消息,但它本身并不具备将消息发送到网络中的功能,因此这一功能需要委托操作系统来实现。
  • 计算机通过集线器连接形成子网,子网又通过路由器连接形成网络。TCP/IP的结构如图所示,就是由一些小的子网,通过路由器连接起来组成一个大的网络:
    在这里插入图片描述
  • 子网中的计算机通过网络号和主机号被唯一识别,网络号和主机号合起来就是IP地址,IP地址是一串十进制数字,通过子网掩码可以区分IP地址中哪部分是网络号,哪部分是主机号。
    在这里插入图片描述
  • 子网掩码为1的部分表示网络号,子网掩码为0的部分表示主机号
    在这里插入图片描述

  • IP地址的主机号:
  1. 全为0:表示整个子网
  2. 全为1:表示向子网上所有设备发送包,即“广播”。

1.2 向DNS服务器查询web服务器的ip地址

  • 通过DNS查询IP地址的操作称为域名解析,负责执行解析(resolution)这一操作的就叫解析器(resolver)。解析器实际上是一段程序,它包含在操作系统的Socket库中(库就是一堆通用程序组件的集合)。Socket库也是一种库,其中包含的程序组件可以让其他的应用程序调用操作系统的网络功能,而解析器就是这个库中的其中一种程序组件。

  • 根据域名查询IP地址时,浏览器会使用Socket库中的解析器,但是解析器只负责封装查询消息,将封装的DNS查询消息发送需要操作系统协议栈的支持。

  • 解析器的用法非常简单。Socket库中的程序都是标准组件,只要从应用程序中进行调用就可以了。具体来说,在编写浏览器等应用程序的时候,只要写上解析器的程序名称“gethostbyname”以及Web服务器的域名“www.lab.glasscom.com”就可以了,这样就完成了对解析器的调用。
    在这里插入图片描述
    在应用程序中编写上图中的一行代码后就能够调用解析器完成向DNS服务器查询IP地址的操作。
    调用解析器后,解析器会向DNS服务器发送查询消息,然后DNS服务器会返回响应消息。响应消息中包含查询到的IP地址,解析器会取出IP地址,并将其写入浏览器指定的内存地址中。

  • 解析器的内部原理:

  1. 网络应用程序调用解析器时,程序的控制流程就会转移到解析器的内部;
  2. 当控制流程转移到解析器后,解析器会生成要发送给DNS服务器的查询消息;
  3. 解析器委托操作系统内部的协议栈发送查询消息(解析器本身不具备使用网络收发数据的功能);
  4. 解析器调用协议栈后,控制流程再次转移,协议栈会执行发送消息的操作,然后通过网卡将消息发送给DNS服务器;
  5. 当DNS服务器收到查询消息后,它会根据消息中的查询内容进行查询,如果要访问的Web服务器已经在DNS服务器上注册,那么这条记录就能够被找到,然后其IP地址会被写入响应消息并返回给客户端;
  6. 接下来,消息经过网络到达客户端,再经过协议栈被传递给解析器,然后解析器读取出消息取出IP地址,并将IP地址传递给应用程序,到这里,解析器的工作就完成了,控制流程重新回到应用程序。
  • DNS服务器的基本工作就是接收来自客户端的查询消息,然后根据消息的内容返回响应。其中,来自客户端的查询消息包含以下3种信息:
    (a)域名:服务器、邮件服务器(邮件地址中@后面的部分)的名称;
    (b)Class:在最早设计DNS方案时,DNS在互联网以外的其他网络中的应用也被考虑到了,而Class就是用来识别网络的信息。不过,如今除了互联网并没有其他的网络了,因此Class的值永远是代表互联网的IN;
    (c)记录类型:表示域名对应何种类型的记录。例如,当类型为A时,表示域名对应的是IP地址;当类型为MX时,表示域名对应的是邮件服务器。对于不同的记录类型,服务器向客户端返回的信息也会不同。

    DNS服务器上事先保存有前面这3种信息对应的记录数据,如图所示,DNS服务器就是根据这些记录查找符合查询请求的内容并对客户端作出响应的。
    在这里插入图片描述

1.3 DNS服务器接力查询

  • DNS服务器中的所有信息都是按照域名以分层次的结构来保存的。域名用句号来分隔不同层次的域名。在域名中,越靠右的位置表示其层级越高。例如 www.qq.com 中最顶级的域为 com 域。
  • 一个域的信息是作为一个整体存放在DNS服务器中的,不能将一个域拆开来存放在多台DNS服务器中。不过,DNS服务器和域之间的关系也并不总是一对一的,一台DNS服务器中也可以存放多个域的信息。
  • 如何找到DNS服务器中存放的信息?
    互联网中有数万台DNS服务器,我们可以采用下面的办法:
    (a)首先,将负责管理下级域的DNS服务器的IP地址注册到它们的上级DNS服务器中,然后上级DNS服务器的IP地址再注册到更上一级的DNS服务器中,以此类推。也就是说,负责管理 www.qq.com 这个域的DNS服务器的IP地址需要注册到 qq.com 域的DNS服务器中,而 qq.com 域的DNS服务器的IP地址又需要注册到 com 域的DNS服务器中。这样,我们就可以通过上级DNS服务器查询出下级DNS服务器的IP地址,也就可以向下级DNS服务器发送查询请求了。
    (b)在互联网中,最顶级的域称为根域,分配给根域DNS服务器的IP地址在全世界仅有13个。将根域的DNS服务器信息保存在互联网所有的DNS服务器中,这样一来,任何DNS服务器都能访问根域服务器,然后通过根域服务器一路顺藤摸瓜找到位于下层的DNS服务器。
    在这里插入图片描述

  • 当然,不是每一次查询都需要从最上级的根域开始查找。DNS服务器具备缓存功能,如果要查询的域名和相关信息已经在缓存中,那么就可以直接返回响应,接下来的查询可以从缓存的位置开始向下进行。相比每次都从根域找起来说,缓存可以减少查询所需的时间。并且,当要查询的域名不存在时,“不存在”这一响应结果也会被缓存。这样,当下次查询这个不存在的域名时,也可以快速响应。同时,DNS服务器中保存的信息都设置有一个有效期,当缓存中的信息超过有效期后,数据就会从缓存中删除。

1.4 委托协议栈发送消息

  • 知道了IP地址,就可以委托操作系统内部的协议栈向目标IP地址发送消息。向操作系统内部的协议栈发出委托时,需要按照指定的顺序调用Socket库中的程序组件。 收发数据的操作分为若干个阶段,可以大致总结为以下4个:
    (a) 创建套接字(创建套接字阶段):客户端创建套接字的操作非常简单,只要调用Socket库中的socket程序组件就可以了。和调用解析器一样,调用socket之后,控制流程会转移到socket内部并执行创建套接字的操作,完成之后控制流程又会被移交回应用程序。套接字创建完成后,协议栈会返回一个描述符,应用程序会将收到的描述符存放在内存中。
    (b)将管道连接到服务器端的套接字上(连接阶段):应用程序通过调用Socket库中的名为connect的程序组件将客户端创建的套接字与服务器那边的套接字连接起来。当调用connect组件时,需要依次提供三个参数:描述符服务器ip地址端口号。连接成功后,协议栈会将对方的ip地址和端口号等信息保存在套接字中。(描述符是用来在一台计算机内部识别套接字的;ip地址端口号是客户端和服务器之间用来识别对方套接字的)。
    (c)收发数据(通信阶段):当套接字连接起来之后,应用程序通过Socket库委托协议栈来进行通信。具体过程如下:
           首先,应用程序需要在内存中准备好要发送的数据(根据用户输入的网址生成的HTTP请求消息)。接下来,当调用Socket库中的write组件时,需要指定描述符和发送数据,然后协议栈就会将数据发送到服务器。由于套接字中已经保存了已连接的通信对象的相关信息,所以只要通过描述符指定套接字,就可以识别出通信对象,并向其发送数据。接着,发送数据会通过网络到达我们要访问的服务器。
           然后,服务器执行接收操作,解析收到的数据内容并执行相应的操作,向客户端返回响应消息。接收消息的操作是通过Socket库中的read程序组件委托协议栈来完成的。调用read程序组件时需要指定用于存放接收到的响应消息的内存地址,这一内存地址称为接收缓冲区。于是,当服务器返回响应消息时,read程序组件就会负责将接收到的响应消息存放到接收缓冲区中。
    (d)断开管道并删除套接字(断开阶段):当浏览器接收到数据之后,收发数据的过程就结束了,接下来需要调用Socket库中的close程序组件,最终套接字之间连接会断开,套接字本身也会被删除。
    在这里插入图片描述

2. 通过电信号传输TCP/IP数据

协议栈会与网卡进行配合,将数据切分成小块并封装成网络包,再将网络包转换成电信号或者光信号发送出去。

2.1 创建套接字

  • 在互联网中传送数据时,数据会被切分成一个一个的网络包,IP模块就负责将网络包发送给通信对象,此外,IP中还包括ICMP协议和ARP协议。ICMP协议用于告知网络包在传送过程中产生的各种错误以及控制消息,ARP用于根据ip地址查询相应的以太网MAC地址。IP下面的网卡驱动程序负责控制网卡硬件,而网卡负责实际的收发操作。

  • 在协议栈内部有一块用于存放控制信息的内存空间,记录了用于通信控制操作的控制信息,例如通信对象的ip地址,端口号,通信操作的进行状态等信息,这些控制信息就是套接字的实体。协议栈就是根据套接字中记录的控制信息进行工作的。

  • Windows中可以通过netstat命令显示套接字信息。
    在这里插入图片描述

  • 创建套接字时,首先协议栈会分配一个用于存放套接字所需的内存空间,然后向其写入初始状态,最终会返回一个描述符。


2.2 连接服务器

创建套接字之后,调用Socket库中的connect组件,就会将本地套接字与服务器的套接字进行连接。

  • 连接实际上就是通信双方交换控制信息,在套接字中记录这些信息并准备收发数据的一连串操作。此外,发当执行数据收发操作时,我们还分配了一块用于临时存储数据的内存空间,我们称作缓冲区,缓冲区也是在连接操作过程中分配的。

  • 控制信息实际上可以分为两类:
    (a)客户端和服务器相互联络时交换的控制信息,这些信息不仅在连接的过程需要,包括数据收发和断开连接操作在内的整个通信过程都需要,这些内容在tcp协议的规格中进行了定义。在这里插入图片描述
    (b)保存在套接字中,用来控制协议栈操作的信息。

  • 连接操作的实际过程:应用程序调用Socket库的connect程序组件与服务器的套接字建立连接。

    connect(<描述符>, <服务器IP地址和端口号>, …)

      上面的调用提供了服务器的IP地址和端口号,这些信息会传递给协议栈中的TCP模块。然后,TCP模块会与该IP地址对应的对象,也就是与服务器的TCP模块交换控制信息,这一交互过程包括下面几个步骤:
(a)客户端先创建一个包含表示开始数据收发操作的控制信息的头部(重点是发送方和接收方的端口号)。到这里,客户端(发送方)的套接字就准确找到了服务器(接收方)的套接字,然后,我们将头部中的控制位的SYN比特设置为1,此外还需要设置适当的序号窗口大小;
(b)当TCP头部创建好之后,接下来TCP模块会将信息传递给IP模块并委托它进行发送。IP模块执行网络包发送操作后,网络包就会通过网络到达服务器,然后服务器上的IP模块会将接收到的数据传递给TCP模块,服务器的TCP模块根据TCP头部中的信息找到端口号对应的套接字,套接字中会写入相应的信息,并将状态改为正在连接。上述操作完成后,服务器的TCP模块会返回响应,这个过程和客户端一样,需要在TCP头部中设置发送方和接收方端口号以及SYN比特为1。此外,在返回响应时还需要将ACK控制位设为1,这表示已经接收到相应的网络包。接下来,服务器TCP模块会将TCP头部传递给IP模块,并委托IP模块向客户端返回响应;
(c)网络包返回到客户端,通过IP模块到达TCP模块,并通过TCP头部的信息确认连接服务器的操作是否成功。如果SYN1则表示连接成功,这时会向套接字中写入服务器的IP地址、端口号等信息,同时还会将状态改为连接完毕。客户端也需要将ACK比特设置为1并发回服务器,告诉服务器刚才的响应包已经收到。当这个服务器收到这个返回包之后,连接操作才算全部完成。

2.3 收发数据

当控制流程从connect组件回到应用程序之后,就进入到收发数据的阶段了,数据收发阶段从应用程序调用write组件将要发送的数据交给协议栈开始的,协议栈接到数据后执行发送操作。

  • 协议栈并不关心应用程序传递的数据内容,在协议栈看来,要发送的数据就是具备一定长度的二进制字节序列。

  • 协议栈在收到数据后,不会立即就发送数据,而是会将数据存放在内部的发送缓冲区,数据累积到一定量时才会发送,到底要累积到多少数据才会发送,不同种类和版本的操作系统会有所区别,但是都会根据以下两个要素来判断:
    (a)每个网络包能够容纳的数据长度:协议栈会根据一个叫做MTU的参数进行判断,MTU表示一个网络包的最大长度,在以太网中一般是1500字节。MTU表示一个包的最大长度,从MTU减去头部的长度就是网络包中容纳的最大数据长度,这个长度叫做MSS
    在这里插入图片描述
    (b)时间:协议栈内部有一个计时器,当经过一定时间后,网络包就会被发送出去。

    MTU和时间是相互矛盾的:如果长度优先,那么网络的效率会提高,但是可能会因为等待缓冲区填满产生延迟;如果时间优先,呢么延迟时间会减少,但是又会降低网络效率。因此,在进行发送操作时要综合考虑以达到平衡。

  • 如果发送缓存区中的数据超过了MSS的长度,缓冲区的内容会被以MSS的长度为单位进行拆分,拆分出来的数据会被放进单独的网络包中,当发送这些数据时,就会在前面添加TCP头部,并且根据套接字中记录的控制信息标记发送方和接收方,然后交给IP模块执行发送数据的操作(IP模块会在网络包中添加IP头部和MAC头部)。
    在这里插入图片描述

  • 数据发送到服务器,TCP还需要确定对方是否成功收到网络包,以及当对方没有收到网络包时进行重发。因此在发送网络包之后还需要进行确认操作:
    (a)首先,TCP模块在拆分数据时,会先算好每一块数据相当于从头开始的第几个字节,接下来在发送这一块数据时,将算好的字节数写在TCP头部中(序号)。然后,发送数据的长度也需要告知接收方(整个网络包的长度减去头部的长度就可以得到数据的长度)。
    (b)通过序号和网络包长度,接收方能够检查收到的网络包有没有遗漏。例如,假设上次接收到第1460字节,那么接下来如果收到序号为1461的包,说明中间没有遗漏;但如果收到的包序号为2921,那就说明中间有包遗漏了。如果确认没有遗漏,接收方会将到目前为止接收到的数据长度加起来,计算出一共已经收到了多少个字节,然后将这个数值写入TCP头部的ACK号中发送给发送方。
    在这里插入图片描述
    注:在实际的通信中,序号并不是从1开始的,而是需要用随机数计算出一个初始值。

  • TCP通信是双向的,客户端向服务器发送数据的同时,服务器也会向客户端发送消息,因此在连接阶段,双方需要互相告知自己的序号初始值。
    在这里插入图片描述

  • TCP通过序号ACK号确认对方是否收到了数据,在得到对方确认之前,发送过的网络包都会保存在发送缓冲区中,如果对方没有返回某些包对应的ACK号,则重发这些包,但是TCP会在尝试几次重传无效之后强制结束通信,并且向应用程序报告错误。

  • 当网络传输繁忙的时候就会发生拥塞,ACK号的返回就会变慢,此时就需要我们将返回ACK号的等待时间设置的稍微长一点,否则就会出现TCP重传了网络包之后,ACK号才姗姗来迟,这种重传是多余的。TCP采用了动态调整等待时间的方法,这个等待时间是根据ACK号返回所需的时间来判断的。具体来说,TCP会在发送数据的过程中持续测量ACK号的返回时间,如果ACK号返回变慢,则相应延长等待时间;相对地,如果ACK号马上就能返回,则相应缩短等待时间。

  • 如果每发送一个包就等待一个ACK号的方式是最简单也最容易理解的,但在等待ACK号的这段时间中,如果什么都不做那实在太浪费了。为了减少这样的浪费,TCP采用滑动窗口方式来管理数据发送和ACK号的操作。所谓滑动窗口,就是在发送一个包之后,不等待ACK号返回,而是直接发送后续的一系列包。这样一来,等待ACK号的这段时间就被有效利用起来了。
    在这里插入图片描述

  • 采用滑动窗口方式来管理数据发送和ACK号的操作能够减少等待ACK号时的时间浪费,但如果不等返回ACK号就连续发送包,就有可能会出现发送包的频率超过接收方处理能力的情况。具体来说就是:当接收方的TCP收到包后,会先将数据存放到接收缓冲区中。然后,接收方需要计算ACK号,将数据块组装起来还原成原本的数据并传递给应用程序,如果这些操作还没完成下一个包就到了,下一个包也会被暂存在接收缓冲区中。但是如果数据到达的速率比处理这些数据并传递给应用程序的速率还要快,那么接收缓冲区中的数据就会越堆越多,最后就会溢出。缓冲区溢出之后,后面的数据就进不来了,因此接收方就收不到后面的包了。我们可以通过下面的方法来避免这种情况的发生。首先,接收方需要告诉发送方自己最多能接收多少数据,然后发送方根据这个值对数据发送操作进行控制,这就是滑动窗口方式的基本思路。

  • 滑动窗口的具体工作方式,参照下图。在这张图中,接收方将数据暂存到接收缓冲区中并执行接收操作。当接收操作完成后,接收缓冲区中的空间会被释放出来,也就可以接收更多的数据了,这时接收方会通过TCP头部中的窗口字段将自己能接收的数据量告知发送方。这样一来,发送方就不会发送过多的数据,导致超出接收方的处理能力了。
    在这里插入图片描述


  • 接收方能够接收的最大数据量称为窗口大小,它是TCP调优参数中非常有名的一个。窗口大小其实就是接收方缓冲区的大小;窗口大小是在动态变化的,与接收方数据处理能力有关。

  • 更新窗口大小的时机:接收方从缓冲区取出数据传递给应用程序的时候,接收方从缓冲区取数据,将数据传递给应用程序,缓冲区容量增加,但是发送方不知道,此时需要告诉发送方,缓冲区容量增大了,即更新窗口大小。

  • 浏览器在委托协议栈发送请求消息后,会调用read组件获取响应消息,然后控制流程会转到协议栈:
    (a)首先,协议栈会检查收到的数据块和TCP头部的内容,判断是否有数据丢失,如果没有问题则返回ACK号;
    (b)然后,协议栈将数据块暂存到接收缓冲区中,并将数据块按顺序连接起来还原出原始的数据,最后将数据交给应用程序。具体来说,协议栈会将接收到的数据复制到应用程序指定的内存地址中,然后将控制流程交回应用程序;
    (c)将数据交给应用程序之后,协议栈还需要找到合适的时机向发送方发送窗口更新。

2.4 从服务器断开并删除套接字

协议栈在设计上允许任何一方发起断开过程,无论哪种情况,完成数据发送的一方会发起断开过程。

  • 以服务器一方发起断开过程为例来进行讲解:
    (a)首先,服务器一方的应用程序会调用Socket库的close程序组件。然后,服务器的协议栈会生成包含断开信息的TCP头部,具体来说就是将控制位中的FIN比特设为1。接下来,协议栈会委托IP模块向客户端发送数据,同时服务器的套接字中也会记录下断开操作的相关信息;
    (b)当客户端收到服务器发来的FIN1的TCP头部时,客户端的协议栈会将自己的套接字标记为进入断开操作状态。然后,为了告知服务器已收到FIN1的包,客户端会向服务器返回一个ACK号;
    (c)这些操作完成后,应用程序就会调用read组件来读取数据。这时,协议栈不会向应用程序传递数据,而是会告知应用程序来自服务器的数据已经全部收到了。因此,客户端应用程序会调用close组件来结束数据收发操作,这时客户端的协议栈也会和服务器一样,生成一个FIN比特为1的TCP包,然后委托IP模块发送给服务器;
    (d)一段时间之后,服务器就会返回ACK号。到这里,客户端和服务器的通信就全部结束了。
    在这里插入图片描述

  • 通信结束之后,用来通信的套接字就不会再使用了,此时就可以删除套接字了。不过,套接字并不会立即被删除,而是会等待一段时间之后再被删除。等待这段时间是为了防止误操作。

TCP通信过程可以使用一张图进行总结:
在这里插入图片描述

2.5 IP与以太网的包收发操作

TCP模块在执行连接、收发和断开等操作时,都需要委托IP模块将数据封装成包发送给通信对象。

  • 包,由头部和数据两部分组成,头部包含了各种控制信息。
    在这里插入图片描述

  • 一个包发往目的地的过程:
    (a)发送方的网络设备会负责创建包,创建包的过程就是生成含有正确控制信息的头部,然后再附加上要发送的数据;
    (b)接下来,包会被发往最近的网络转发设备。当到达最近的转发设备之后,转发设备会根据头部中的信息判断接下来应该发往哪里。这个过程需要用到一张表,这张表里面记录了每一个地址对应的发送方向,也就是按照头部里记录的目的地址在表里进行查询,并根据查到的信息判断接下来应该发往哪个方向;
    (c)包在向目的地移动的过程中,又会到达下一个转发设备,然后又会按照同样的方式被发往下一个转发设备。就这样,经过多个转发设备的接力之后,包最终就会到达接收方的网络设备。
    在这里插入图片描述

  • 网络中有路由器和集线器两种不同的转发设备,它们在传输网络包时有着各自的分工:
    (a)路由器根据目标地址判断下一个路由器的位置;
    (b)集线器在子网中将网络包传输到下一个路由;
    实际上,集线器是按照以太网规则传输包的设备,而路由器是按照IP规则传输包的设备。

  • TCP/IP包包含如下两个头部:
    (a)IP头部(用于IP协议);发送方将包的目的地,也就是要访问的服务器的IP地址写入IP头部中。IP协议就可以根据这一地址查找包的传输方向,从而找到下一个路由器的位置;
    (b)MAC头部(用于以太网协议):IP协议会委托以太网协议将网络包传输给服务器,此时,IP协议会查找下一个路由器的以太网地址(MAC地址),并将这个地址写入MAC头部中。
    在这里插入图片描述

  • TCP模块委托IP模块收发包的过程就是:
    (a)TCP模块在数据块的前面加上tcp头部,然后整个传递给IP模块;
    (b)IP模块收到委托之后,会将包的内容当做一个整体(tcp头部+数据),然后在前面加上包含控制信息的头部(ip头部和mac头部);
    (c)接下来,封装好的包会交给网络硬件(由一连串01组成的数字信息),网络硬件会将这些数字信息转换成电信号或者光信号,通过网线发送出去;
    (d)电信号或者光信号到达路由器等转发设备,再由转发设备一步一步转发到目标对象。
    在这里插入图片描述

  • IP模块接收TCP模块的委托负责网络包的收发操作,它会生成ip头部并且添加到tcp头部前面,ip头部内容如表所示:
    在这里插入图片描述

  • IP地址实际上并不是分配给计算机的,而是分配给网卡的,因此当计算机上存在多块网卡时,每一块网卡都会有自己的IP地址。可以通过route print命令来显示路由表:
    在这里插入图片描述

  • IP模块在生成ip头部之后,还会在ip头部前面添加mac头部。mac头部的字段如图所示:
    在这里插入图片描述

  • 通过ARP(地址解析协议)查询目标路由器的MAC地址,ARP就是利用广播获取目标对象的MAC地址。
    在这里插入图片描述

  • 但是,不是每次发送包都要去查询一次,将查询结果放到ARP缓存,在发送包时,先查询一下ARP缓存,如果其中已经保存了对方的MAC地址,就不需要发送ARP查询,直接使用ARP缓存中的地址,而当ARP缓存中不存在对方MAC地址时,则发送ARP查询。
    在这里插入图片描述

  • 以太网是一种为多台计算机能够彼此自由和廉价地相互通信而设计的通信技术。尽管以太网经历了数次变迁,但其基本的3个性质至今仍未改变:
    (a)将包发送到MAC头部的接收方MAC地址代表的目的地;
    (b)用发送方MAC地址识别发送方;
    (c)用以太类型识别包的内容。
    在这里插入图片描述

  • IP模块生成的网络包只是存放在内存中的一串数字信息,需要将数字信息转换为电信号(光信号),才能进行传输,执行这一操作的是网卡。但是网卡也无法单独工作,还需要通过网卡驱动程序对网卡进行控制。网卡的内部结构如图所示(此概念图不代表网卡硬件的实际结构):
    在这里插入图片描述

  • 网卡不是上电就会立马工作的,还需要进行初始化。即打开计算机启动操作系统的时候,网卡驱动程序会对硬件进行初始化操作,然后硬件才会进入可使用的状态。

  • 网卡的ROM保存的是网卡的mac地址,这个是在生产网卡的时候写入的。也有一些特殊的的方法比如通过命令或者配置文件读取mac地址并分配给MAC模块。这种情况下网卡会忽略ROM中的mac地址。网卡中ROMmac地址真正生效的是网卡驱动初始化时在MAC模块中设置的那个mac地址。

  • 网卡驱动从IP模块获取网络包之后,会将其复制到网卡内的缓冲区,然后向网卡的MAC模块下达发送包的命令,接下来就轮到网卡的MAC模块进行工作:
    (a)MAC模块会将网络包从缓冲区取出,并在开头加上报头起始帧分界符,在末尾加上用于检测错误的帧校验序列
    在这里插入图片描述

  • 报头是一串像10101010...这样10交替出现的比特序列,长度为56比特。报头的作用是确定包的读取时机(通过报头测量时钟信号)。起始帧分界符长度为8比特,用来确定帧的起始位置
    在这里插入图片描述

  • 用电信号表示数字信息时,通过测量信号中的电压和电流变化,还原出01两种比特的值。但是测量电压和电流时必须判断出每个比特的界限在哪,通过在数据信号之外,再发送一组用来区分比特间隔的时钟信号,当时钟信号变化时读取电压和电流的值,让01进行对应即可。
    在这里插入图片描述注释:图中c,解决距离较远时,网线较长,两条线路的长度会发生差异,数据信号和时钟信息的传输会产生时间差,时钟会发生偏移的问题。

  • 帧校验序列(FCS)用来检验网络包传输过程中,因噪声导致的波形紊乱,数据错误,它是一串长度为32比特的序列,是通过公式对包中从头到尾的内容进行计算得到的。接收方计算出的FCS和发送方计算的FCS如果不同,就说明数据出现了错误。

  • 网络包通过网卡的MAC模块添加了报头起始帧分界符帧校验序列后就可以通过网线发送了。发送信号的操作分为两种:
    (a)半双工模式(集线器):某一时刻,只能进行发送或接收其中一种操作。发送之前要判断网线中是否存在其它设备发送的信号,如果有,则需要等待该信号传输完毕,因为如果有其他设备发送的信号,此时再发送信号就会产生信号碰撞
    (b)全双工模式(交换机):发送和接收同时并行。

  • 网卡的MAC模块从报头开始将数字信息按每个比特转换成电信号,然后由PHY(Physical Layer Device,物理层装置),或者叫MAU(Medium Attachment Unit,介质连接单元)的信号收发模块发送出去。将数字信息转换为电信号的速率就是网络的传输速率。接下来,PHY(MAU)模块将信号转换为可在网线上传输的格式,并且通过网线发送出去。

  • 在半双工模式中,一旦发生信号碰撞,两组信号就会相互叠加,无法彼此区分出来。这种情况下:
    (a)发送操作会终止。为了通知其他设备当前线路已发生碰撞,还会发送一段时间的阻塞信号,然后所有的发送操作会全部停止;
    (b)等待一段时间之后,网络中的设备会尝试重新发送信号。但如果所有设备的等待时间都相同,那肯定还会发生碰撞,因此必须让等待的时间相互错开。具体来说,等待时间是根据MAC地址生成一个随机数计算出来的;
    (c)当网络拥塞时,发生碰撞的可能性就会提高,重试发送的时候可能又会和另外一台设备的发送操作冲突,这时会将等待时间延长一倍,然后再次重试。以此类推,每次发生碰撞就将等待时间延长一倍,最多重试10次,如果还是不行就报告通信错误。

  • 网卡接收网络包时的操作过程:
    (a)在使用集线器的半双工模式以太网中,一台设备发送的信号会到达连接在集线器上的所有设备。接收操作的第一步就是把这些信号全都收进来。信号的开头是报头,通过报头的波形同步时钟,然后遇到起始帧分界符时开始将后面的信号转换成数字信息。这个操作和发送时是相反的,即PHY(MAU)模块先开始工作,然后再轮到MAC模块。首先,PHY (MAU)模块会将信号转换成通用格式并发送给MAC模块,MAC模块再从头开始将信号转换为数字信息,当到达信号的末尾时,还需要检查FCS。如果FCS校验有问题,包就会被当作错误包被丢弃;
    (b)如果FCS校验没有问题,接下检验MAC头部中接收方MAC地址与网卡在初始化时分配给自己的MAC地址是否一致,如果不一致就直接丢弃,如果接收方MAC地址和自己MAC地址一致,则将包放入缓冲区中;
    (c)接下来网卡会使用中断机制通知计算机收到了一个网络包。具体来说,中断的工作过程是这样的:首先,网卡向扩展总线中的中断信号线发送信号,该信号线通过计算机中的中断控制器连接到CPU;当产生中断信号时,CPU会暂时挂起正在处理的任务,切换到操作系统中的中断处理程序;然后,中断处理程序会调用网卡驱动,控制网卡执行相应的接收操作。中断是有编号的,网卡在安装的时候就在硬件中设置了中断号,在中断处理程序中则将硬件的中断号和相应的驱动程序绑定。当网卡发起中断时,就会自动调用网卡驱动了;
    (d)网卡驱动被中断处理程序调用后,会从网卡的缓冲区中取出收到的包,并通过MAC头部中的以太类型字段判断协议的类型,网卡驱动就会把包交给对应的协议栈。

2.6 UDP协议的收发操作

像DNS查询等交换控制信息的操作基本上都可以在一个包的大小范围内解决,这种场景中就可以用UDP来代替TCP。UDP没有TCP的接收确认、窗口等机制,因此在收发数据之前只要在从应用程序获取的数据前面加上UDP头部,然后交给IP模块进行发送就可以了。UDP接收也很简单,只要根据IP头部中的接收方和发送方IP地址,以及UDP头部中的接收方和发送方端口号,找到相应的套接字并将数据交给相应的应用程序就可以了。除此之外,UDP协议遇到错误或者丢包也一概不管。因为UDP只负责单纯地发送包而已,并不像TCP一样会对包的送达状态进行监控,所以协议栈也不知道有没有发生错误。
在这里插入图片描述

3. 从网线到网络设备

信号在传输过程中会衰减,还会受到噪声干扰失真。
交换机会先接收信号,然后将信号还原成数字信息,再转换为电信号将包发送出去。
路由器基于IP工作,负责对包进行转发。路由器还具备将私有地址转换为共有地址的地址转换功能以及阻止危险网络包的包过滤等附加功能。

3.1 信号在网线和集中器中传输

  • 信号在传输过程中,能量会逐渐损失,网线越长(一般不要超过100米),信号衰减越严重。以太网中信号是方波信号,能量的损失会使得信号的拐角变圆(电信号频率越高,能量损失越多)。
    在这里插入图片描述

  • 双绞线利用“双绞”抑制噪声。
    噪声的产生是因为网线周围存在电磁波。当电磁波接触到金属等导体时,就会产生与原本信号不同的电流,信号和噪声产生的电流混杂在一起,就会导致信号的波形失真。
    影响网线的电磁波分为两种:
    (a)外源性:来自电机、荧光灯等外源设备泄漏出来的电磁波。信号线是用金属做成的,当电磁波接触到信号线时,会沿电磁波传播的右旋方向产生电流,这种电流会导致波形发生失真。如果我们将信号线缠绕在一起,信号线就变成了螺旋形,其中两根信号线中产生的噪声电流方向就会相反,从而使得噪声电流相互抵消,噪声就得到了抑制;
    (b)内源性:传输的信号本身就是一种电流,当电流流过时就会向周围发出电磁波,这些电磁波对于其他信号线来说就成了噪声。这种内部产生的噪声称为串扰。要抑制串扰,关键在于双绞线的缠绕方式。在一根网线中,每一对信号线的扭绞间隔(节距)都有一定的差异,这使得在某些地方正信号线距离近,另一些地方则是负信号线距离近。由于正负信号线产生的噪声影响是相反的,所以两者就会相互抵消。从网线整体来看,正负的分布保持平衡,自然就会削弱噪声的影响。
    在这里插入图片描述

  • 集线器将信号发送给所有连接在它上面的线路。

3.2 交换机的包转发操作

  • 交换机根据地址表进行转发:
    (a)信号到达网线接口,由PHY(MAU)模块进行接收,接下来PHY(MAU)模块将信号转换为通用格式,然后传递给MAC模块;
    (b)MAC模块(交换机端口的MAC模块不具备MAC地址)将信号转换为数字信息,然后通过包末尾的FCS校验错误,如果没有问题则存放到缓冲区;
    (c)查询MAC地址表,找到网络包的接收方MAC地址对应的端口,通过交换电路(有些产品不是使用的交换电路)转发出去;
    (d)当网络包通过交换电路到达发送端口时,端口中的MAC模块和PHY(MAU)模块会执行发送操作,与网卡的发送操作一样,也要检查信号碰撞
    在这里插入图片描述

  • 交换电路可以将输入端和输出端连接起来。其中,信号线排列成网格状,每一个交叉点都有一个交换开关,交换开关是电子控制的,通过切换开关的状态就可以改变信号的流向。交换电路的输入端和输出端分别连接各个接收端口和发送端口,网络包通过这个网格状的电路在端口之间流动。每个交叉点上的交换开关都可以独立工作,因此只要路径不重复,就可以同时传输多路信号。
    在这里插入图片描述

  • 交换机在转发包的过程中还需要对MAC地址表进行维护:
    (a)收到包时,将发送方的MAC地址及输入端口号写入MAC地址表;
    (b)删除过时的记录。

  • 交换机在特殊情况下的操作:
    (a)交换机查询地址表之后发现记录中的目标端口就是这个包的源端口,交换机会直接丢弃这个包;
    (b)地址表中找不到指定的MAC地址,交换机会把包转发到除了源端口之外其它所有的端口;
    (c)接收方地址是一个广播地址,交换机会把包转发到除了源端口之外其它所有的端口。

  • 交换机使用全双工模式,可以同时进行发送和接收操作。

  • 通过自动协商,可以自动在全双工模式和半双工模式直接进行切换,并且还能探测对方的传输速率然后进行切换。
    在以太网中,当没有数据在传输时,网络中会填充一种被称为连接脉冲的脉冲信号。在没有数据信号时就填充连接脉冲,从而能够检测对方是否在正常工作,或者说网线有没有正常连接。以太网设备的网线接口周围有一个绿色的LED指示灯,它表示是否检测到正常的脉冲信号。如果绿灯亮,说明PHY(MAU)模块以及网线连接正常。
    自动协商功能就利用脉冲信号,将自己能够支持的工作模式和传输速率相互告知对方,并从中选择一个最优的组合。
    在这里插入图片描述

3.3 路由器的包转发操作

网络包经集线器和交换机转发到了路由器,路由器与交换机类似,也是通过查询内部的转发表确定包转发的目标。但是路由器是基于IP设计的,而交换机是基于以太网设计的。

  • 路由器包括转发模块和端口模块两部分。其中转发模块负责判断包转发目的地;端口模块负责包的收发操作。
    在这里插入图片描述

  • 路由器的基本工作原理:路由器在转发包时,首先会通过端口将发过来的包接收进来(取决于端口对应的通信技术)。对于以太网端口来说,就是按照以太网规范进行工作,而无线局域网端口则按照无线局域网的规范工作,总之就是委托端口的硬件将包接收进来。接下来,转发模块会根据接收到的包的IP头部中记录的接收方IP地址,在路由表中进行查询,以此判断转发目标。然后,转发模块将包转移到转发目标对应的端口,端口再按照硬件的规则将包发送出去,即转发模块委托端口模块将包发送出去。

  • 路由器的端口是以实际的发送方和接收方的身份来收发网络包的。以以太网端口为例,路由器的端口具有mac地址,因此能够成为以太网的发送方和接收方。此外,路由器的端口还具备ip地址。

  • 路由器根据网络包IP头部的ip地址判断转发目标。路由表如下图所示:
    (a)左侧的目标地址列记录的是接收方的信息(实际上这里的ip地址只包含表示子网的网络号部分的比特值,而表示主机号部分的比特值全部为0)。路由器会将接收到的网络包的接收方ip地址与路由表中的目标地址进行比较,并找到相应的记录。交换机在地址表中只匹配完全一致的记录,而路由器则会忽略主机号部分,只匹配网络号部分。打个比方,路由器在转发包的时候只看接收方地址属于哪个区,××区发往这一边,××区发往那一边。
    (b)在匹配地址的过程中,路由器需要知道网络号的比特数,通过子网掩码就可以判断出网络号的比特数。
    (c)网关表示要转发的目标对象ip地址。
    (d)接口,执行转发的路由器端口。
    (e)跃点数,表示距离目标ip地址的距离的远近,数字越小,表示距离目标ip地址越近。

在这里插入图片描述

  • 路由表的子网掩码只表示在匹配网络包目标地址时需要对比的比特数量。有时地址本身的子网掩码和路由表中的子网掩码是不一致的,这是路由聚合的结果。路由聚合会将几个子网合并成一个子网,并在路由表中只产生一条记录。例如,现在有3个子网,分别为10.10.1.0/2410.10.2.0/2410.10.3.0/24,路由器B需要将包发往这3个子网。正常情况下,路由器B的路由表中应该有对应这3个子网的3条记录,但在这个例子中,无论发往任何一个子网,都是通过路由器A来进行转发,因此我们可以在路由表中将这3个子网合并成10.10.0.0/16,这样也可以正确地进行转发,但减少了路由表中的记录数量。经过路由聚合,多个子网会被合并成一个子网,子网掩码会发生变化,同时,目标地址列也会改成聚合后的地址。
    在这里插入图片描述

  • 与交换机维护记录表(交换机维护记录表是包转发操作的一个步骤)的方式不同,路由器对路由表的维护是与包转发操作相互独立的。对路由表的维护大致分类如下:
    (a)人工手动维护;
    (b)根据路由协议机制,通过路由器之间的信息交换由路由器自行维护路由表。

  • 路由器的整个工作过程(以以太网端口为例):
    (a)首先,路由器会接收网络包。信号到达网线接口部分,其中的PHY(MAU)模块和MAC模块将信号转换为数字信息,然后通过包末尾的FCS进行错误校验,如果没问题则检查MAC头部中的接收方mac地址,如果是发送给自己的就放到接收缓冲区中,否则就丢弃这个包。
    (b)完成包接收操作之后,路由器就会丢弃包开头的MAC头部。MAC头部的作用就是将包送达路由器,其中的接收方mac地址就是路由器端口的mac地址。因此,当包到达路由器之后,MAC头部的任务就完成了,于是MAC头部就会被丢弃。
    (c)接下来,路由器会根据MAC头部后方的IP头部中的内容进行包的转发操作。转发操作分为几个阶段:首先是查询路由表判断转发目标。有时候路由表中会存在网络号长度相同的多条记录,这时,需要根据跃点计数的值来进行判断(选择跃点计数小的记录)。如果在路由表中无法找到匹配的记录,路由器会丢弃这个包,并通过ICMP消息告知发送方。
    (d)找不到匹配路由时可以选择默认路由。将子网掩码设置为0.0.0.0,无论任何地址都能匹配到这一条记录,只要在这一条记录的网关列中填写接入互联网的路由器地址,当匹配不到其他路由时,网络包就会被转发到互联网接入路由器。因此这条记录被称为默认路由,这一行配置的网关地址被称为默认网关
    (e)从路由表中查找到转发目标之后,网络包就会被转交给输出端口,并最终发送出去,但在此之前,路由器还要更新IP头部中的TTL(Time to Live,生存时间)字段。TTL字段表示包的有效期,包每经过一个路由器的转发,这个值就会减1,当这个值变成0时,就表示超过了有效期,这个包就会被丢弃。这个机制是为了防止包在一个地方陷入死循环。
    (f)以太网的包发送操作是根据以太网规则来进行的,即便设备种类不同,规则也是相同的。也就是说,其基本过程和协议栈中的IP模块发送包的过程是相同的,即在包前面加上MAC头部,设置其中的一些字段,然后将完成的包转换成电信号并发送出去。首先,为了判断MAC头部中的mac地址应该填写什么值,需要根据路由表的网关列判断对方的地址。如果网关是一个ip地址,则这个ip地址就是我们要转发到的目标地址;如果网关为空,则IP头部中的接收方ip地址就是要转发到的目标地址。知道对方的ip地址之后,接下来需要通过ARP根据ip地址查询mac地址,并将查询的结果作为接收方mac地址。路由器也有ARP缓存,因此首先会在ARP缓存中查询,如果找不到则发送ARP查询请求。接下来是发送方MAC地址字段,这里填写输出端口的mac地址。
    (g)网络包完成后,接下来会将其转换成电信号并通过端口发送出去。这一步的工作过程和计算机也是相同的。如果输出端口为以太网,则发送出去的网络包会通过交换机到达下一个路由器。由于接收方mac地址就是下一个路由器的地址,所以交换机会根据这一地址将包传输到下一个路由器。接下来,下一个路由器会将包转发给再下一个路由器,经过层层转发之后,网络包就到达了最终的目的地。

3.4 路由器的附加功能

路由器还有很多附加功能,最重要的有两种:地址转换包过滤

  • ip地址分为两类:
    (a)公有地址;
    (b)私有地址,私有地址的范围仅限:10.0.0.0~10.255.255.255172.16.0.0~172.31.255.255192.168.0.0~192.168.255.255

  • 当内网和互联网连接的时候,要将内网分成两个部分,一部分是对互联网开放的服务器,另一部分是内部设备。其中对互联网开放的部分分配公有地址,可以和互联网直接通信。相对地,内网部分则分配私有地址,内网中的设备不能和互联网直接收发网络包,而是通过地址转换机制进行连接。
    在这里插入图片描述

  • 地址转换的基本原理是在转发网络包时对IP头部中的ip地址和端口号进行改写。具体过程如下:
    (a)首先,TCP连接操作的第一个包被转发到互联网时,会将发送方ip地址从私有地址改写成公有地址。这里使用的公有地址是地址转换设备的互联网接入端口的地址。与此同时,端口号也需要进行改写(在对外只能使用一个公有地址的情况下,可以用不同的端口号来区别内网中的不同终端设备),地址转换设备会随机选择一个空闲的端口。然后,改写前的私有地址和端口号,以及改写后的公有地址和端口号,会作为一组相对应的记录保存在地址转换设备内部的一张表中;
    (b)改写发送方ip地址和端口号之后,包就被发往互联网,最终到达服务器,然后服务器会返回一个包。服务器返回的包的接收包是原始包的发送方,因此返回的包的接收方就是改写后的公有地址和端口号。这个公有地址其实是地址转换设备的地址,因此这个返回包就会到达地址转换设备;
    (c)接下来,地址转换设备会从地址对应表中通过公有地址和端口号找到相对应的私有地址和端口号,并改写接收方信息,然后将包发给公司内网,这样包就能够到达原始的发送方了。在后面的包收发过程中,地址转换设备需要根据对应表查找私有地址和公有地址的对应关系,再改写地址和端口号之后进行转发;
    (d)当数据收发结束,进入断开阶段,访问互联网的操作全部完成后,对应表中的记录就会被删除。
    在这里插入图片描述

  • 对于从内网访问互联网的包,即便其发送方私有地址和端口号没有保存在对应表中也是可以正常转发的,因为用来改写的公有地址就是地址转换设备自身的地址,而端口号只要随便选一个空闲的端口就可以了,这些都可以由地址转换设备自行判断。然而,对于从互联网访问公司内网的包,如果在对应表中没有记录就无法正常转发。因为如果对应表中没有记录,就意味着地址转换设备无法判断公有地址与私有地址之间的对应关系。解决方法也很简单,手动添加一条对应的记录即可。

  • 包过滤就是在对包进行转发时,根据MAC头部、IP头部、TCP头部的内容,按照事先设置好的规则决定是转发这个包,还是丢弃这个包。通常防火墙设备或软件,大多数都是利用这一机制来防止非法入侵的。但要想设置一套恰当的规则来区分非法访问和正常访问,只阻止非法入侵而不影响正常访问,是非常不容易的。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值