网络基础 — 网络模型与网络协议

前言

从这一小节,我们开始梳理网络相关的知识结构。网络对于程序员非常重要,可以说离开了网络软件程序就失去了70%的魔力。但是程序员对于网络相关的领域是又爱又恨,爱是因为网络赋予程序无限的可能性,恨是因为网络对软件开发来说几乎是透明的,不用刻意的去调整网络,我们也能进行业务的开发。掌握网络相关的知识并不容易,网络相关的领域的知识内容复杂且涉及范围广。可是如果要成为一个优秀的开发工程师,进行网络相关的开发,就必须对这个部分有一个清晰的结构化的认知。这一小节,我们会从网络的TCP五层模型和OSI七层结构模型开始梳理介绍,随后介绍每一层和每一层具有代表性的网络协议,最后我们简单的聊一聊一个数据包是怎么在网络上传输的。

网络模型基础

这个模型我相信大家在大学都学过,基本上网络的知识都是围绕着这个网络结构展开的。其中我们学习过两种网络模型,一种是OSI七层模型,另外一种是TCP/IP五层模型。其中OSI七层模型包括应用层、表示层、会话层、传输层、网络层、数据链路层和物理层。而TCP/IP五层模型包括应用层、传输层、网络层、数据链路层和物理层。OSI七层模型更加侧重功能,而TCP/IP更加侧重于协议。

OSI七层和TCP/IP五层的区别:

  1. TCP/IP 是一个协议簇;而OSI是一个模型,且TCP/IP的开发时间在OSI之前。

  2. TCP/IP是由一些交互性的模块做成的分层次的协议,其中每个模块提供特定的功能;OSI则指定了哪个功能是属于哪一层的。

  3. TCP/IP是五层结构,而OSI是七层结构。OSI的最上面的三层在TCP中用应用层表示。

TCP/IP的五层分别为:应用层、传输层、网络层、数据链路层和物理层。前面我们提到TCP/IP五层结构是由一些交互性的模块做成的分层次的协议,那么他们每一层有哪些协议?以下列举了我们接触的比较多的网络协议。

  • 应用层:HTTPHTTPSFTPSMTPTelnet

  • 传输层:TCPUDP

  • 网络层:IPICMP

  • 数据链路层:ARP

  • 物理层:…

OSI七层模型分为:应用层、表示层、会话层、传输层、网络层、数据链路层和物理层。OSI更偏向哪个功能属于哪一层。那么这些网络功能都在那层呢?

  • 应用层:文件传输、电子邮件、文件服务、虚拟终端等。

  • 表示层:数据格式化、代码转换、数据加密。

  • 会话层:解除或建立与其他接点的联系。

  • 传输层:提供端对端的接口。

  • 网络层:为数据包选择路由。

  • 数据链路层:传输有地址帧,错误检测的功能。

  • 物理层:以二进制数据形式在物理媒体上传输数据。

将这两个模型总结成如下表格:

OSI模型 TCP/IP五层模型 功能 协议
应用层 应用层 文件传输、电子邮件等 HTTP、FTP、SMTP、Telnet等
表示层 数据格式化,代码转换,数据加密
会话层 建立或者解除与其他连接点的联系
传输层 传输层 提供端对端的接口 UDP、TCP
网络层 网络层 为数据包提供路由 IP、ICMP等
数据链路层 数据链路层 传输有地址帧、错误检测 ARP等
物理层 物理层 二进制物理介质传输数据 ISO2110、IEEE802、IEEE802.2等网络传输协议

一个数据包的奇幻之旅

我们上面介绍了网络模型,但是这些网络模型又和实际的传输有什么关系呢?当我们访问一个网站,背后的数据又是怎么进行传输的呢?我在读书的时候也都知道有网络协议,但是让我说一些传输的细节,我却很难答上来,这个部分我们简单介绍一个数据包的传输过程,建立起一个数据传输过程的基本认知。

封包与拆包

在网络上传输的并不是直接的数据,而是一个个数据包。每个数据包经过发送端都会被带上一些特殊信息,这些特殊信息在到达中间或目标设备是会被读取,这些特殊信息就是协议头。数据包在发送端添加协议头的过程叫做封包数据包在接收端被拆分读取分析的过程叫做拆包。如果我们传输的应用层使用的是HTTP协议,传输过程和封包拆包示例如下。

MAC头与IP头

如果我们要把一个数据包从一个网络设备发送到另一个网络设备,IP头必不可少,但是为了在到达目标局域网后快速找到目标接收端,我们的数据包还需要MAC头,IP头和MAC之间的关系类似于我们信封上的收件地址和收件人姓名。数据包有了这两个协议头,就可以通过网络从一端传输到另一端。以下是这两个协议头的细节图。

在MAC头里面,显示目标MAC地址,然后是源MAC地址,然后有一个协议类型,用来说明里面的IP协议类型。IP头里面的版本号,目前主流的还是IPv4。IP头里面还有个8位标识协议,这里指的是传输层协议类型,也就是TCP,还是UPD协议。这里最重要的是源IP地址和目标IP地址。(IP协议下面有详细介绍。)

在数据包在网络上传输过程中,这个IP头和MAC头在有些时候并不是一尘不变的,随着网段的切换,这个IP头和MAC头也会切换。在任何一台机器上,当要访问另一个IP地址的时候,都先要判断目标IP地址和当前机器的IP地址,是否在同一个网段。

  • 如果在同一个网段,这就好比在公司你访问你旁边同事电脑一样,这里数据包的传输过程中不用进过网关就能访问。在封包过程中,直接将源地址和目标地址放入IP头中,然后通过ARP获得MAC地址,将源头MAC和目的MAC地址放入MAC头,然后发送出去就好了。
  • 如果不是同一个网关,这个时候就要先把数据包发给网关Gateway。网关Gateway地址一定是和源IP地址是同一个网段的。往往不是第一个地址就是第二个地址。

网关是一个三层转发设备,往往是一个路由器、三层交换机或是防火墙。它是一个网段的入口也是出口,就很类似与我们现实生活中的海关,这个出口连接着多个网段。如果一个数据包传输过程中跨网段,网关匹配上IP地址和MAC地址之后,三层设备会读取数据包并根据目标IP地址,匹配转发的网段,匹配到之后,三层设备会重新给数据包打上下一个目标地址的IP头和MAC头直到跳到目标设备或在网络中被丢弃为止。

路由过程分析

接下来我们通过分析在同一网段和在不同网段场景下,数据包在网络中的路由过程是怎样。在这个过程中数据包的IP头和MAC头又会发生哪些变化。

转发网关路由场景分析

上面这张图,我们可以发现服务器A要访问服务器B,其中左边的路由器为路由器A,右侧的路由器为路由器B。目标服务器192.168.4.101/24和源服务器192.168.1.101/24不在同一个网段,因而需要先把数据包发送给网关。其中网关已经配置好了为192.168.1.1/24,同时通过ARP获取网关的MAC地址 ,然后发送数据包。其中包中的MAC头和IP头信息如下。

  • 源MAC:服务器的A的MAC地址。

  • 目标MAC:192.168.1.1这个网口的MAC地址。

  • 源IP:192.168.1.101

  • 目标IP: 192.168.4.101

当数据包到达网关192.168.1.1后,路由器A通过查询路由表发现,如果需要访问192.168.4.101需要从192.168.56.1这个口出去,到达下一跳192.168.56.2。因此路由器通过ARP获得192.168.56.2的MAC地址,并将包发出去,其中包中的MAC头和IP头信息如下:

  • 源MAC:192.168.56.1的MAC地址。

  • 目标MAC:192.168.56.2的MAC地址。

  • 源IP:192.168.1.101

  • 目标IP: 192.168.4.101

当数据包到达192.168.56.2这个网口,后来路由B通过查询路由表,如果想要192.168.4.101/24目标IP,需要从192.168.4.1/24这个口出去并且目标IP也是我们要反问的服务器B,因此这一跳也是最后一跳。通过ARP协议获取192.168.4.1/24的MAC地址后把数据包发出去,其中包中的MAC头信息和IP头信息如下:

  • 源MAC:192.168.4.1/24 的MAC地址。

  • 目标MAC:192.168.4.101/24 的MAC地址。

  • 源IP:192.168.1.101

  • 目标IP: 192.168.4.101

通过这个过程可以看出,每到一个新的局域网,MAC地址都是要变的,但是IP地址不变。在IP头里面,不会保存任何网关的IP地址,所谓下一跳,是要将目标IP转换为MAC地址放入MAC头,目标IP地址在整个过程过程中不会发生改变。这是转发网关的路由过程。

NAT网关路由场景分析

这个场景和上面场景有一些不同,其中访问的源服务器A和目标的服务器B的IP地址是相同的。他们两个在不同的局域网中,这个场景很像我日常访问学校选课系统一样。服务器A是我们自己电脑,现在我们要访问学校的选课系统,选课系统部署在机房的局域网中,选课系统服务器B的IP地址为192.168.1.101/24,碰巧我们宿舍的电脑在宿舍这个局域网内也是192.168.1.101/24这个IP地址。它为了能对外提供服务,还需要一个外网地址192.168.56.2/24。现在我们服务器A要向服务器B发送数据包,首先服务器A先从DNS解析获取服务器B域名对应的IP地址即192.168.56.2/24。这个地址不是和服务器A在一个局域网,所以我们将数据包发送给网关。数据包中的IP地址和MAC地址如下:

  • 源MAC:服务器的A的MAC地址。

  • 目标MAC:192.168.1.1这个网口的MAC地址。

  • 源IP:192.168.1.101

  • 目标IP: 192.168.56.2

数据包到达网关192.168.1.1后,通过查询路由表,应该走192.168.56.1/24这个口出去,并且目标192.168.56.2就是下一跳。通过ARP获取到192.168.56.2/24的MAC地址,并且将数据包发送出去。

这里需要注意⚠️,这里我们的网关是NAT网关,在外网上传输如果使用192.168.1.101局域网的IP地址,接收端无法知道通过一个局域网的IP地址定位到发送端,所以这里我们的源IP地址应该是NAT网关的地址,回来的数据包发送到这个网关只要通过一定的映射关系就能找到回来的数据包中的IP地址对应的服务器。这也就是NAT网关的特殊之处,其中NAT的全称为(Network Address Translation)。

这里我们的数据包的头信息如下,不难发现这个时候我们源IP地址和MAC地址已经变成了NAT网关A的IP地址和MAC地址。

  • 源MAC:192.168.56.1/24的MAC地址。

  • 目标MAC:192.168.56.2/24的MAC地址。

  • 源IP:192.168.56.1

  • 目标IP:192.168.56.2

包到达192.168.56.2NAT网关之后,192.168.56.2的外网地址映射的是内网服务器B的地址为192.168.1.101/24,通过ARP获取服务器B的MAC地址之后,将数据包发送给服务器B,注意这里的网关是NAT网关,所以这里的源的MAC地址会替换成局域网的NAT网关MAC地址,其中数据包中头信息如下:

  • 源MAC:192.168.1.1 的MAC地址。

  • 目标MAC:192.168.1.101 的MAC地址。

  • 源IP:192.168.56.1

  • 目标IP:192.168.1.101

至此,NAT网关的路由场景路由结束了。我们仔细观察不难发现,NAT网关和转发网关的区别在于NAT会做IP地址的映射转换,可以让多个设备通过一个IP地址进行数据访问。极大了解决了IPv4地址总量不足的问题。但是正是NAT网关的存在,这导致如果我们没有将服务地址映射到公网上,我们就无法通过外网直接访问我们私人服务。同时,我们访问外网服务,一个局域网内的设备使用的都是一个IP地址,即出口NAT网关地址。

这里还有一个注意的点:NAT转换的时候还有一个NAPT协议,即Network Address Port Translation,数据包发出的时候,NAT路由会将数据包中的局域网IP和端口转换为NAT的公共IP和NAT动态分配的端口,并且建立映射关系。等数据包回来的时候,NAT路由会依据这个转换后的NAT动态端口转换为局域网的IP地址和端口。

数据包出: 局域网IP:端口 ==NAT==> NAT公共IP:动态端口

数据包入: NAT公共IP:动态端口 ==NAT ==> 局域网IP:端口

这里还有一个没有介绍的点,就是我们的路由策略路由算法,其中有我们可以配置的静态路由策略和在路由过程中的动态路由算法。如果有感兴趣的朋友,可以查询有关资料深入,这里就不展开了,展开了又能讲一大堆了。😅😅

协议?你我之间的约定!

我刚开始接触到协议的时候,了解到什么TCP/IP协议,UDP协议各种各样的协议都有种不明觉厉的感觉。但是随着我深入的学习,编写自己的RPC的网络协议的时候,发现协议并没有想象中的那么神秘,协议只不过是收发端约定的规则而已,更像是我们写信中,大家约定的书信格式一样。没了协议双方网络能通么?当然是可以的,只不过我不知道你发的是什么信息了。因此我们这的协议是网络协议的简称,网络通信计算机双方必须共同遵循的一组约定,如怎样建立连接、怎么样互相识别等。只有遵守了这个约定,计算机之间才能互相通信交流。我们将从数据链路层自下向上依次梳理各个层代表协议。物理层过于物理,这里我们就不梳理了。

数据链路层

数据链路层也叫MAC层,MAC层的全程是Medium Access Control,即媒体访问控制。其实就是控制媒体上发数据的时候,谁先发、谁后发的问题。防止发生混乱,即多路访问。主要有以下三种协议:信道划分轮流协议随机接入协议

ARP协议

ARP协议是一个工作在数据链路层的协议。ARP协议解决了什么样问题呢?我们都知道在网络包传输需要一个IP地址和一个MAC,如果IP地址可以类比成你的地址,MAC地址就是你的名字。IP地址我们可以通过查询DNS服务器获得,那么MAC地址怎么办?这个时候就需要ARP协议。通过IP协议获取目标设备的MAC地址,这就是ARP协议的工作目标。

那如果如果通过IP地址获取的目标的MAC地址呢?其实很简单,在局域网中发送一个ARP请求,这个请求是以广播的形式发出去的,如果某一台机器收到ARP请求,并且发现要查询的IP地址和自己的一致,则返回自己的MAC地址。发送端收到这个目标机器的MAC地址后,为了避免每次都要发ARP包询问MAC地址,发送端会将这个地址缓存一段时间,方便后续的使用。

其中ARP协议发送的报文结构如下所示:

网络层

网络层是OSI模型中的第三层,介于传输层和数据链路层之间,它在数据链路层提供的两个相邻端点之间的数据帧的传输功能上,进一步管理网络中的数据通信,将数据设法从源端经过若干个中间节点传输到目的地端,从而向传输层提供基本的端到端的数据传输服务。我们熟知的IPICMP(ping命令)协议就工作在这一层。

IP协议

IP协议是TCP/IP协议族的核心协议,其中包括两个方面:

  • IP头部信息。IP头部信息出现在每个IP数据报中,用于指定IP通信的源端IP地址、目标端IP地址,以及指定部分通信行为
  • IP数据报的路由和转发。IP数据报的路由和转发发生在除目标机器之外的所有主机和路由器上。他们决定数据报是否应该转发以及如何转发。

IP 协议的核心即定义了数据包从哪来到哪去,以及这个过程中在网络终端上的转发行为

IP协议特点

IP协议是TCP/IP协议簇的基石,它为上层协议提供无状态、无连接、不可靠的服务。

  • 无状态是指IP通行双方不传输数据的状态信息,因此所有IP数据报的发送、传输都是相互独立的,没有上下文关系。这种服务最大的缺点就是无法处理乱序和重复的IP数据报。面向连接的协议,比如TCP协议,能够自己处理乱序的、重复的报文段,它递交给上层协议的内容绝对是正确且有序的。

    无状态服务的有点也很明显:简单、高效。我们无需为保持维护通信状态而消耗系统资源,也无需在每次传输时都携带状态。

  • 无连接是指IP通信双方都不会长久的维持对方的任何信息,这样上层协议在每次发送数据的时候都必须指明对方的IP地址。

  • 不可靠指的是IP协议不能保证数据包一定能准确的到达,它只是承诺尽最大努力。很多情况都可以导致IP数据报发送失败,比如,某个路由器发现数据包在网络上存在时间太长,就会将它丢弃,并返回一个ICMP错误消息给发送端。

因此IP服务上层协议往往需要自己实现数据确认,超时重传等机制,以达到安全可靠传输的目的。典型实现TCP协议。

IPv4协议头

IPv4的协议头如下所示,一般长度为20个字节(如下面的5层),也有可能包含变长部分总长超过20个字节。

  • 4位头部长度标识这个这个IP报文头长度,标识能有多少个4个字节,因此IP报文头最长 15 * 4 = 60个字节。

  • 8位服务类型包括一个三位的优先权字段,4位的TOS字段和1位保留字段(必须置0)。4位TOS字段分别为:最小延时,最大吞吐量,最高可靠性和最小费用。其中最多有一位可以置1,应用程序应该根据实际需要来设置。比如SSH和Telnet这样登录需要最小延时服务,而传输文件的ftp则需要最大吞吐服务。

  • 16位总长度指的是整个IP数据报的长度,以字节为单位。因此IP数据报文最长为65535个字节,但是由于MTU的限制,数据报文长度超过MTU限制就会进行分片传输。

IP协议的 MTU 是物理设备上的限制,它限制了路径上能够发送数据包大小的上限。

  • 16位标识唯一标识主机发送地每一个数据报。其初始值由系统随机生成,每发送一个数据报,其值就加一,该值在数据报分片时被复制到每个分片中,因此同一个数据报中的所有分片都具有相同的标识。
  • 3位标识字段第一位保留。第二表示”禁止分片”**。如果设置了这个位,IP服务将不对数据报进行分片,在这种情况下,如果IP数据报超过MTU限制,后续的数据报会被丢弃并返回一个ICMP的差错报文。第三位表示”更多分片”。除了数据报的最后一个分片以外,其他分片都要把它置为1。**
  • 13位分片偏移是分片相对原始IP数据报开始处的偏移,实际的偏移量则是左移动3位(*8)后得到,因此除了最后一个分片以外,每个IP分片的数据部分长度必须数8的倍数。
  • 8位生存时间(TTL)是数据报到达目的地之前允许经过的路由器跳数。TTL在发送时被设置(常见值64)。数据报文在转发过程中每经过一个路由,该值就被路由器减1,当TTL减为0时,数据包会被丢弃,并且向源发送一个ICMP差错报文。TTL可以防止数据报陷入路由循环。
  • 8位协议用来区分上层协议,其中 ICMP是1,TCP是6,UDP是17。
  • 32位源端地址和32位目标端地址 。我们前面提到了IP协议是无状态,无连接的。因此每次发送数据都要携带目标端的IP地址,同样为了能让目标段给源端发响应数据包,IP头中还会带一个源端地址。这两个IP地址在某个局域网内传输时候,不会发生改变。但是经过网关的时候,NAT协议会将源和目标的MAC地址和IP地址进行替换。
  • IPv4最后一个选项是一个可变的最多为40个字节的可选信息。因为头部固定占了20个字节且IP头最大可以有60个字节,所以这个可选信息最多40个字节。这个部分可以记录以下几种信息:
    • 记录路由,沿途进过的路由。
    • 时间戳,可用于计算每个路由之间的传输时间。
    • 路由选择(松散路由选择、严格路由选择),指定路由过程中必须经过或全部必须经过的路由。

路由与转发

IP协议的一个核心的任务是数据报文的路由,即决定数据报到目标机器的路径。

简单分析上面的图从左下角的IP输入队列开始。

  • 当IP模块接收到来自数据链路层的IP数据报,它首先对该数据报的头部做CRC校验,确认无误后就分析头部的具体信息。

  • 如果该IP数据报的头部中目标IP地址是本机的某个IP地址,或者是广播地址,即该数据包是给本机的,则IP模块就根据数据报头部中的协议字段来决定将它派发给某个上层应用协议如果不是发现这个数据报不是给本机的,则也调用数据报转发子模块来处理该数据报。

  • 数据报转发模块会检测系统是否允许转发,如果不允许,数据报将会被丢弃。如果允许,数据转发模块将会对数据报进行一些操作,然后交给IP报文输出模块

转发模块会做如下操作:

  1. 检查数据报文头部的TTL值,如果TTL值已经是0,则丢弃该数据报。

  2. 检查数据头部的严格路由选择选项,如果该选项被设置,则检查数据报的目标IP地址是否是本机的某个IP,如果不是,发送一个ICMP差错报文给发送端。

  3. 如果有必要,则给源端发送一个ICMP重定向报文,以告诉它一个更合理的下一跳路由。

  4. 将TTL的值减1

  5. 处理IP头部选项

  6. 如果有必要,执行IP分片操作。

  • IP数据报应该发送至哪个下一跳路由(或目标主机),以及经过哪个网卡来发送,就是IP路由过程,即图中“计算下一跳路由模块。IP模块实现数据报路由的核心数据结构是IP路由表。这个表按照数据报的目标IP地址分类,同一类型的IP数据报将会被发往相同的下一跳路由或目标主机。
  • IP输出队列中存放的是所有等待发送的IP数据报。
  • 图中的虚线箭头显示了路由表更新的过程,这一过程指的通过路由协议或者route命令调整路由表,使之更快适应新的网络拓扑结构,成为IP路由策略。

IP的路由策略:

  1. 查找路由表中的数据报的目标IP地址完全匹配的主机IP地址。如果找到,就使用该路由项,没找到转步骤2。

  2. 查找路由表中的数据报目标IP地址具有相同网络ID的网络IP地址。如果找到,就使用该路由项,没找到转步骤3。

  3. 选择默认路由项,这通常意味着数据报的下一跳是网关。

ICMP协议

我们通常在网络不是很好的时候,习惯使用ping命令去检查下网络的情况。而ping命令则是基于ICMP协议工作的。ICMP 全称 Internet Control Message Protocol。即互联网控制报文协议。这里面的具体怎么“控制”的呢?网络包在异常复杂的网络环境中传输时,常常会遇到各种各样的问题。当遇到问题的时候,我们不能直接忽视问题。而是需要去探查问题的情况,然后根据结果来调整传输策略。ICMP报文是封装在IP包里面的,并且本身足够轻量以方便探测。

ICMP报文有很多种类型,不同的类型有不同的代码。最常用的类型是主动请求为8,主动请求的应答为0。

查询报文类型

ICMP查询报文类型,即主动探测网络的报文类型。我们常用的ping命令就是查询报文,是一种主动请求,并且获得主动应答的ICMP协议。因此ping发出的包也是符合ICMP协议格式的,只不过它在后面增加了自己的格式。

对于ping 主动请求,进行网络抓包,称为ICMP ECHO REQUEST。同理主动请求的回复,称为ICMP ECHO REPLY。比起原生的 ICMP,这里多了两个字段,一个是标识符号,另外一个是序号,在选项数据中,ping 还会存放发送请求的时候,来计算往返时间,说明路程的长短。

差错报文类型

如果一切顺利,我们我们收到主动请求回复,但是如果不顺利,那么我们就会收到差错报文不同的异常情况也对应着不同的差错报文类型。其中比较常见的例子:终点不可达为 3, 源抑制为 4,超时为 11,重定向为 5

  • 终点不可达:就是字面意思,目标不可达。

  • 源抑制:让源站放慢发送速度。

  • 时间超时:超过了网络包的生存时间,但是网络包还是没有达到目标端。

  • 重定向:下次发给另外一个路由。

Traceroute:差错报文类型的使用

我之前会用traceroute命令去查看,数据包经过了哪些路由器,经过了多少跳。而traceroute通过设置特殊的TTL,来追踪去往目的地沿途经过的路由器。当使用traceroute命令指向某个地址时,它会发送一个UDP的数据包,并且将TTL设置为1。这样遇到第一个路由,路由就会发现这个数据包“生命结束”了,并返回一个ICMP的差错报文类型是时间超时,这个报文里面就带有了这个路由器的IP地址。然后源端发送第二个UDP数据包,并将TTL设置为2。这个时候遇到第二个路由时就会返回一个ICMP差错报文。同理这样就可以一步步拿到沿途经过的路由IP。当然也有路由器压根就不会返回 ICMP差错报文,所以我们会看到输出“*”了。traceroute 还有一个作用就是故意不设置不分片,从而测试网络路径的MTU。

传输层

传输层位于TCP/IP协议族中的第4层,这一层的协议为应用进程提供端到端的通信服务。它提供面向连接的数据流支持、可靠连接、流量控制和多路重用等服务。这一层主要的协议有TCPUDP

UDP协议

UDP是User Datagram Protocol的简称,中文名是用户数据报协议。UDP是一种无连接传输层协议,提供简单不可靠的信息传送服务。它在传输过程中并不会与目标端建立一个“连接”,只是简单的把数据包丢入网络中,然后任其自生自灭。如果把UDP比喻成人的话,UDP就像是一个相信世界美好的孩子。相信网路链路的“美好”即相信发出即可送达,没有经验也不会去处理一些拥塞,丢包的异常场景。

这里提到了一个“连接”,这个连接是抽象的,并不是真的有两个通信端之间有一个类似“网线”一样的东西,他们只是靠通信的两端维护一定的数据结构保持某种状态,来记录和维护这样一个“连接”的状态。

UDP的包头如下,通过包头我们也不难发现这是个简单没有什么复杂“想法”的协议。

UDP的特点与使用场景

通过上面对UDP的介绍我们很容易就可以了解到UDP的特点:

  • 轻量简单
  • 不能应对复杂的网络情况,没有流量控制,没有应答机制,不能处理丢包、重发、错序等问题。

UDP虽然简单,但是简单也有简单的用法。基于这些特点,我们也可以用在以下的场景中:

  1. 需要资源少,网络情况比较好的内网,或者对于丢包不敏感的应用。DHCP协议就是基于UDP的,DHCP中一般获取IP地址都是内网请求,而且可以重复多次获取请求。

  2. 不需要一对一建立连接,而是可以进行广播的应用。UDP不面向连接的功能,可以使用承载广播或者多播的协议。DHCP就是一种广播形式的协议。

  3. 需要处理速度快,延时低,可以容忍少数丢包,但是要求即便网络拥塞也不能降低速率。UDP简单、处理速度快,在例如直播、游戏等实时性要求比较高的场景中,丢了一两个包也无关紧要,但是如果延时过高则很难接受,这种场景中也基本使用UDP进行传输。

简单并不代表低级,简单同时也意味着更高的可拓展性。

同时因为UDP简单,可自定义拓展性也更高,因此现在也有不少基于UDP特性拓展出来上层协议和应用领域。

  1. QUIC(全称 Quick UDP Internet Connections,快速UDP互联网连接)是Google 提出的一种基于UDP改进的通信协议,其目的是降低网络通行的延迟,提供更好的用户互动体验。QUIC在应用层上,会自己实现快速连接,减少重传时延,自适应拥塞控制。

  2. 流媒体协议,现在很多直播协议是基于RTMP的,RTMP是基于TCP实现的流媒体协议,但是流媒体协议要求较高的实时性,现在很多直播平台都基于UDP实现了自己的流媒体传输协议。

  3. 实时游戏领域,同理,如果想要更高的实时性,TCP并不是一个好的选择,基于UDP的实现的传输协议能带来更好的实时性游戏体验。

  4. IoT 物联网,物联网领域的终端往往都是嵌入式的系统,内存小性能差,可能维护一个TCP连接对于这些系统来说都是一个不小的开销。而且物联网也要求较高的实时性,Google 旗下的 Nest 建立的 Thread Group 推出的 Thread 物联网通行协议就是基于UDP的。

  5. 移动通信领域。在4G网络里,移动流量上网的数据面对的协议 GTP-U是基于UDP的,因为移动通信协议本身就比较复杂,如果基于TCP,TCP的机制就会显得非常多余。

TCP协议

前面我们介绍的UDP协议是面向无连接,不可靠的协议。而与UDP协议刚好相反,TCP是面向连接,提供可靠的传输层协议。其中我们熟知的HTTPFTPSMTPTELNETSSH等应用层协议都是基于可靠的TCP协议进行传输的。在复杂的网络环境中,保证可靠且高效的传输并非是一件容易的事。TCP协议通过三次握手四次挥手来建立稳定可靠的连接,通过应答机制、滑动窗口和拥塞窗口等流量控制手段来保证传输的可靠性。最后通过各种拥塞算法实现对网络带宽的充分利用。由于TCP协议涉及内容篇幅较长,我们会在下一小结进行详细分析和解读。😉

TCP协议的算法设计能带来很多思想层面的启示。✊🏼

应用层

在传输层的上层应用层有很多的协议,这些协议基于TCP的可靠传输和UDP的简单低延迟的特点,可以“玩出了很多花样“,其中有我们熟悉的用于邮件收发的SMTP协议,文件传输的FTP协议和用于服务器的SSHTELNET协议等。当然还有我们最熟悉的用于WEB服务的HTTP协议。这里我们就不对HTTP协议的细节进行展开了,毕竟这个协议我们每天开发过程中多多少少都会用到。但是有一个问题我们聊到,就是HTTP1HTTP2之间的区别。说实话HTTP2我也用的少,我们日常开发中的请求也基本都是HTTP1

HTTP1与HTTP2 之间的区别

HTTP/2(超文本传输协议第2版,最初命令为HTTP2.0),是HTTP协议的第二个版本,使用于万维网。HTTP/2是HTTP协议自1999年HTTP 1.1 发布后的首个更新,主要基于SPDY协议(是Google开发的基于TCP的应用层协议,用以最小网络延迟,提升网速,优化用户使用体验)。主要区别集中于下面四个方面:

  1. HTTP/2 采用二进制格式而非文本格式。

  2. HTTP/2 是完全多路复用的,而非有序并阻塞的,只需要一个连接即可实现并行。

  3. 通过压缩包头,HTTP/2降低了开销。

  4. HTTP/2让服务器可以将主动的“推送”到客户端缓存中。

二进制协议

最新的HTTP版本在功能和属性(例如从文本协议转换为二进制协议)方面已经有了重大发展,HTTP1.x用于处理文本命令已完成请求-响应周期。HTTP/2将使用二进制命令执行相同的任务,此属性减轻了框架的复杂性,并简化了由于包含文本和可选空格的命令而导致混淆的命令和实现。使用HTTP/2实现的浏览器会将相同的文本命令转换为二进制命令,然后再通过网络传输。

请求多路复用

HTTP/1.x有个问题叫线端阻塞(head-of-blocking),它是指一个连接(connection)一次只提交一个请求的效率比较高,多了就会变慢。HTTP/1.1试过用流水线(pipelining)来解决这个问题,但是效果并不理想(数据量较大或者速度较高的响应,会阻碍排在他后面的请求),此外,由于网络媒介(intermediary)和服务器不能很好的支持流水线,导致部署起来困难重重。而多路传输(Multiplexing)能很好的解决这些问题,因为它能同时处理很多个消息的请求和响应;甚至可以在传输过程中将一个消息和另一个掺杂在一起。所以客户端只需要一个连接就能加载一个页面。

标头压缩

HTTP/2压缩大量冗余头帧。它使用HPACK规范作为标头压缩的简单安全方法。客户端和服务器都在维护在先前的客户端-服务器请求中使用的标头列表。HPACK 在将每个标头传输到服务器之前先压缩每个标头的单独值,然后服务器在先前传输的标头值列表中查找编码信息,以重建完整的标头信息。

HTTP/2服务器推送

此功能使用服务器可以向客户端发送其他未缓存的信息,但这些信息会在以后的请求中得到预期。例如客户端请求资源X,并且可以理解资源Y被请求文件引用,则服务器可以选择将Y与X一起推送,而不是等待适当的客户端请求。

总结

这个部分我们介绍了大家大学基本上都记过的计算机网络模型,其中包括OSI七层模型,TCP/IP五层模型,其中OSI七层模型更多的是针对特定的功能来进行划分的,而TCP/IP五层模型则更多的针对的是协议划分,我们软件开发也更侧重于TCP/IP的五层模型。其中我们介绍了每一层都有哪些代表协议,不知道你现在还能不能记起来。在第二个部分,我们介绍了一个数据包是流转于模型的每一层之间,并且介绍了这个数据包是如何在网络上进行传输的。在最后一个大模块中,我们顺着模型从下往上介绍了每一层具有代表性的网络协议。在数据链路层,我们介绍了用于获取mac地址的ARP协议,网络层介绍了扛把子IP协议和网络探子ICMP协议,传输层则介绍了傻白甜的UDP协议和给TCP协议挖的一个坑。最后应用层,我们简单提了下HTTP/1和HTTP/2之间的区别。通过这一小节的梳理,基本上对网络也有了一个大体认知。下一节我们将深入梳理TCP协议,看看TCP是如何保证数据包又好又快地在复杂的网络环境中传输的。

学习资料