第一章–TCP/IP 协议族

TCP / IP 协议族体系结构以及主要协议

TCP / IP 协议族是一个四层协议系统 :

  • 数据链路层
  • 网络层
  • 传输层
  • 应用层

*每一层完成相应的功能, 并且通过若干协议实现, 上层协议使用下层协议提供的服务*

Screenshot_2022-09-03-19-59-06-755_com.miui.gallery

数据链路层

  • 实现了网卡接口的网络驱动程序, 以处理数据在物理媒介上的传输

    物理媒介 : 以太网, 令牌环等…

    不同的物理网络具有不同的电气特性, 网络驱动程序隐藏了这些细节, 为上层协议提供了一个统一的接口

  • 数据链路层的常用协议

    • APR 协议 (Address Resolve Prosolve, 地址解析协议)

    • RARP 协议 (Reverse Address Resolve Protocol, 逆地址解析协议)

    这两种协议实现了**IP 地址和机器物理地址 ( 通常为 MAC 地址)**的相互转换


网络层

  • 实现数据包的选路和转发

    WAN (Wide Area NetWork 广域网)通常使用众多分级的路由器来连接分散的主机和 LAN (Local Area Network 局域网), 因此, 通信的两台主机一般不是直接相连的, 而是通过多个中间节点 (路由器) 连接的.

    网络层的任务就是选择这些中间系欸按, 以确定两台主机之间的通信路径

    网络层对上层协议隐藏了网络拓扑连接的细节, 使得传输层和网络应用程序看来, 通信的双方是直接相连的

  • 核心协议

    • IP 协议(Internet Protocol, 因特网协议)

      IP 协议根据数据包的目的 IP 地址来决定如何投递它

      如果数据包不能直接发送给目标主机, 那么 IP 协议就为它寻找一个合适的下一条路由器, 并将数据包交给该路由器转发, 然后重复这一过程

    • ICMP 协议 (Internet Control Message Protocol, 因特网控制报文协议)

      该协议是 IP 协议的重要补充

      主要用于检测网络连接


传输层

  • 为两台主机上的应用程序提供端到端的通信

    传输层只关心通信的起始端和目的端, 不在乎数据包的传输过程

  • 主要协议

    • TCP 协议

      为应用层提供给可靠的, 面向连接的和基于流的服务

      使用超时重传, 数据确认等方式来确保数据包被正确的发送到目的端

    • UDP 协议

      为应用层提供不可靠的, 无连接和基于数据报的服务

      数据在传输过程中丢失, 或者目的端通过数据校验发现数据错误而丢弃, UDP 仅通知应用程序发送失败

    • SCTO 协议
      一种相对较新的传输层协议, 为了因特网上传输电话信号而设计


应用层

  • 负责处理应用程序的逻辑

    与数据链路层, 网络层, 传输层不同, 应用层在用户空间实现, 因为它负责众多逻辑

    如 : 文件传输, 名称查询和网络管理…等等

  • 协议举例

    • telnet 协议

      一种远程登录协议,

    • OSPF (Open Shortest Path Fisrst, 开放最短路径优先)协议

      一种动态路由更新协议, 用于路由器之间的通信, 以告知对方各自的信息

    • DNS (Domain Name Service 域名服务)协议

      提供机器域名到 IP 地址的转换

  • 应用层协议(或程序) 可能跳过传输层直接使用网络层提供的服务

    如 : Ping 程序和 OSPF 协议

  • 通常既可以使用 TCP 服务, 又可以使用 UDP 服务

    如 : DNS 协议


封装

下层协议将接口封装, 供给上层协议调用

应用数据发送到网络前, 将沿着协议从上到下依次传递, 每层协议都将在上层数据的基础上加上自己的头部信息 (有时还有尾部信息), 以实现该层的功能, 这个过程就叫封装

数据报

Screenshot_2022-09-03-21-14-42-016_com.miui.gallery

  • 经过 TCP 封装, 形成TCP 报文段

    TCP 报文段包含 TCP 头部信息, TCP 内核缓冲区

    Screenshot_2022-09-03-21-17-01-579_com.miui.gallery

    当发送端应用程序使用 send(或者 write)函数向一个 TCP 连接写入数据时

    • 内核中的 TCP 模块首先把这些数据复制到与该连接对应的 TCP 内核发送缓冲区中
    • TCP 模块调用 IP 模块提供的服务,传递的参数包括 TCP 头部信息和 TCP 发送缓冲区中的数据,即 TCP 报文段。
  • 经过 UDP 封装, 形成UDP 数据报

    与 TCP 不同, UDP 传输数据后, 无需为应用层数据保存副本

  • 经过 IP 封装, 形成IP 数据报

    IP 数据报也包含头部部分和数据部分, 数据部分就是一个 TCP 报文段, UDP 数据报或者 ICMP 报文


经过数据链路层封装的数据称为帧

媒介不同, 帧的类型也不同

  • 以太网帧
  • 令牌环帧

帧的最大传输单元(MTU), 规定帧最多能携带多少上层协议数据


分用

当帧到达目的主机时, 将沿着协议栈自底向上依次传递

信息发送时, 沿着协议栈自上向下传递,相当于对信息进行包装,

接收时, 沿着协议栈自底向上传递, 相当于对信息拆包

Screenshot_2022-09-03-21-31-35-642_com.miui.gallery

  • 由于 IP 协议, ARP 协议和 RARP 协议都是用帧传输, 所以帧头部需要加上标识字段来区分他们

    具体情况取决于帧的类型

    以以太网帧为例,它使用 2 字节的类型字段来标识上层协议

    如果主机接收到的以太网帧类型字段的值为 0x800,则帧的数据部分为 IP 数据报,以太网驱动程序就将帧交付给 IP 模块;

    若类型字段的值为 0x806,则帧的数据部分为 ARP 请求或应答报文,以太网驱动程序就将帧交付给 ARP 模块;若类型字段的值为 0x835,则帧的数据部分为 RARP 请求或应答报文,以太网驱动程序就将帧交付给 RARP 模块。

    a

  • 同样, 因为 ICMP, TCP, UCP 协议都是用 IP 协议, 所以 IP 数据报在头部使用了 16 位来区分他们

TCP 报文段和 UDP 数据报则通过其头部中的 16 位的端口号(port number)字段来区分上层应用程序。

比如 DNS 协议对应的端口号是 53,HTTP 协议(Hyper-Text Transfer Protocol,超文本传送协议)对应的端口号是 80。


ARP 协议工作原理

以太网 APR 请求 / 应答报文详解

Screenshot_2022-09-03-21-42-31-888_com.miui.gallery

  • 硬件类型字段定义物理地址的类型

    它的值为 1 表示 MAC 地址。

  • 协议类型字段表示要映射的协议地址类型

    它的值为 0x800,表示 IP 地址。

  • 硬件地址长度字段和协议地址长度字段

    顾名思义,其单位是字节。

    对 MAC 地址来说,其长度为 6;

    对 IP(v4)地址来说,其长度为 4。

  • 操作字段指出 4 种操作类型:

    • ARP 请求 (值为 1)
    • ARP 应答 (值为 2)
    • RARP 请求(值为 3)
    • RARP 应答(值为 4)
  • 最后 4 个字段指定通信双方的以太网地址和 IP 地址。

    • 发送端填充除目的端以太网地址外的其他 3 个字段,以构建 ARP 请求并发送之。
    • 接收端发现该请求的目的端 IP 地个址是自己,就把自己的以太网地址填进去,
    • 然后交换两个目的端地址和两个发送端地址,以构建 ARP 应答并返回之(当然,如前所述,操作字段需要设置为 2)

ARP 高速缓存的查看和修改

通常,ARP 维护一个高速缓存,其中包含经常访问(比如网关地址)或最近访问的机器的 IP 地址到物理地址的映射。这样就避免了重复的 ARP 请求,提高了发送数据包的速度。
Linux 下可以使用 arp 命令来查看和修改 ARP 高速缓存。

比如,emest-laptop 在某一时刻(注意,ARP 高速缓存是动态变化的)的 ARP 缓存内容如下(使用 arp-a 命令):

1
2
Kongming20 (192.168.1.109) at 08:00:27:53:10:67 [ether] on etho
?(192.168.1.1) at 14:e6:e4:93:5b:78 [ether] on etho

其中,第一项描述的是另一台测试机 器 Kongming20(注意,其 IP 地址、MAC 地址都与图 1-8 描述的一致 )

第二项描述的是路由器。

下面两条命令则分别删除和添加一个 ARP 缓存项:

1
2
$ sudo arp -d 192.168.1.109							#删除Kongming20对应的ARP缓存项
$ sudo arp -s 192.168.1.109 08:00:27:53:10:67 #添加Kongming20 对应的ARP缓存项

DNS 工作原理

DNS 是一套分布式的域名服务系统

每个 DNS 服务器上都存放着大量的机器名和 IP 地址的映射, 并且是动态更新的

众多网络客户端程序都使用 DNS 协议来向 DNS 服务器查询目标主机的 IP 地址

DNS 查询和应答报文详解

DNS 查询和应答报文的格式如下

Screenshot_2022-09-03-21-54-15-123_com.miui.gallery

16 位标识字段用于标记一对 DNS 查询和应答,以此区分一个 DNS 应答是哪个 DNS 查询的回应

16 位标志字段用于协商具体的通信方式和反馈通信状态。

DNS 报文头部的 16 位标志字段的细节如下图所示。

Screenshot_2022-09-03-21-58-28-346_com.miui.gallery

  • QR,查询/应答标志。

    0 表示这是一个查询报文,1 表示这是一个应答报文。

  • opcode,定义查询和应答的类型。

    0 表示标准查询,1 表示反向查询(由 IP 地址获得主机域名),2 表示请求服务器状态。

  • AA,授权应答标志,仅由应答报文使用。

    1 表示域名服务器是授权服务器。

  • TC,截断标志,仅当 DNS 报文使用 UDP 服务时使用。

    因为 UDP 数据报有长度限制,所以过长的 DNS 报文将被截断。

    1 表示 DNS 报文超过 512 字节,并被截断。

  • RD,递归查询标志。

    1 表示执行递归查询

    即如果目标 DNS 服务器无法解析某个主机名,则它将向其他 DNS 服务器继续查询,如此递归,直到获得结果并把该结果返回给客户端。

    0 表示执行迭代查询

    即如果目标 DNS 服务器无法解析某个主机名,则它将自己知道的其他 DNS 服务器的 IP 地址返回给客户端,以供客户端参考。

  • RA,允许递归标志。

    仅由应答报文使用,1 表示 DNS 服务器支持递归查询。

  • zero,这 3 位未用,必须都设置为 0。

  • rcode,4 位返回码,表示应答的状态。

    常用值有 0(无错误)和 3(域名不存在)。

接下来的 4 个字段则分别指出 DNS 报文的最后 4 个字段的资源记录数目。对查询报文而言,它一般包含 1 个查询问题,而应答资源记录数、授权资源记录数和额外资源记录数则为 0。应答报文的应答资源记录数则至少为 1,而授权资源记录数和额外资源记录数可为 0 或非 0。

Linux 下访问 DNS 服务

我们要访问 DNS 服务,就必须先知道 DNS 服务器的 IP 地址。Linux 使用/etc/resolv.conf 文件来存放 DNS 服务器的 IP 地址。

Linux 下一个常用的访问 DNS 服务器的客户端程序是 host,比如下面的命令是向首选 DNS 服务器 219.239.26.42 查询机器 www.baidu.com的IP地址:

1
2
3
4
$ host -t A www.baidu.com
www.baidu.com is an alias for www.a.shifen.com. #以下均输出
www.a.shifen.com has address 119.75.217.56
www.a.shifen.com has address 119.75.218.77

host 命令的输出告诉我们,机器名 www.baidu.comwww.a.shifen.com.的别名,并且该机器名对应两个IP 地址

host 命令使用 DNS 协议和 DNS 服务器通信,其 -t 选项告诉 DNS 协议使用哪种查询类型。

我们这里使用的是 A 类型,即通过机器的域名获得其 IP 地址(但实际上返回的资源记录中还包含机器的别名)

关于 host 命令的详细使用方法,请参考其 man 手册


socket 和 TCP / IP 协议族的关系

数据链路层, 网络层, 传输层协议是在内核中实现的, 因此操作系统需要实现一组系统调用, 使得应用程序能够访问这些协议提供的服务

实现组系统调用的 API 主要有两套:

Socket

XTI

XTI 现在基本不再使用, 这里只讨论 socket

由 socket 定义的这一组 API 提供如下两点功能:

  • 将应用程序数据从用户缓冲区中复制到 TCP/UDP 内核发送缓冲区,以交付内核来发送数据(比如 send 函数 )

    或者是从内核 TCP/UDP 接收缓冲区中复制数据到用户缓冲区,以读取数据

  • 应用程序可以通过它们来修改内核中各层协议的某些头部信息或其他数据结构,从而精细地控制底层通信的行为

    比如可以通过 setsockopt 函数来设置 IP 数据报在网络上的存活时间

socket 是一套通用网络编程接口,它不但可以访问内核中 TCP/IP 协议栈,而且可以访问其他网络协议栈(比如 X.25 协议栈、UNIX 本地域协议栈等)。