《Linux高性能服务器编程》第一章笔记


现在Internet使用的主流协议族是TCP协议族。它是一个分层、多协议的通信体系。本章简要讨论TCP/IP协议族各层包含的主要协议,以及它们之间是如何协作完成网络通信的。
本章则简单介绍其中几个相关协议:ICMP协议、ARP协议和DNS协议。

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

TCP/IP协议族是一个四层协议系统,自底而上分别是数据链路层网络层传输层应用层。每一层完成不同的功能,且通过若干协议来实现,上层协议使用下层协议提供的服务
在这里插入图片描述

1.1.1 数据链路层

数据链路层实现了网卡接口的网络驱动程序,以处理数据在物理媒介( 比如以太网、令牌环等)上的传输。不同的物理网络具有不同的电气特性,网络驱动程序隐藏了这些细节,为上层协议提供一个统一的接口

ARP协议(地址解析协议)、RARP协议(逆地址解析协议):实现了IP地址和MAC地址之间的相互转换。

网络层使用IP地址寻址一台机器,而数据链路层使用物理地址寻址一台机器,因此网络层必须先将目标机器的IP地址转化成其物理地址,才能使用数据链路层提供的服务,这就是ARP协议的用途。
RARP协议仅用于网络上的某些无盘工作站。因为缺乏存储设备,无盘工作站无法记住自己的IP地址,但它们可以利用网卡上的物理地址来向网络管理者(服务器或网络管理软件)查询自身的IP地址。运行RARP服务的网络管理者通常存有该网络上所有机器的物理地址到IP地址的映射。

1.1.2 网络层

网络层实现数据包的路由和转发。WAN (Wide Area Network,广域网)通常使用众多分级的路由器来连接分散的主机或LAN (Local Area Network,局域网), 因此,通信的两台主机一般不是直接相连的,而是通过多个中间节点(路由器)连接的。网络层的任务就是选择这些中间节点,以确定两台主机之间的通信路径。同时,网络层对上层协议隐藏了网络拓扑连接的细节,使得在传输层和网络应用程序看来,通信的双方是直接相连的
网络层最核心的协议是IP协议(Intermet Protocol,因特网协议)。IP协议根据数据包的目的IP地址来决定如何投递它。如果数据包不能直接发送给目标主机,那么IP协议就为它寻找一个合适的下一跳 (next hop)路由器,并将数据包交付给该路由器来转发。多次重复这一过程,数据包最终到达目标主机,或者由于发送失败而被丢弃。可见,IP协议使用逐跳(hop by hop)的方式确定通信路径。

1.1.3 传输层

传输层为两台主机上的应用程序提供端到端(end to end)的通信。与网络层使用的逐跳通信方式不同,传输层只关心通信的起始端和目的端,而不在乎数据包的中转过程。下图展示了传输层和网络层的这种区别:
在这里插入图片描述
图中垂直的实线箭头表示TCP/IP协议族各层之间的实体通信(数据包确实沿着这些线路传递的),而水平的虚线箭头表示逻辑通信线路。

传输层协议主要有三个:TCP协议、UDP协议、SCTP协议。

TCP为应用层提供可靠地、面向连接的、基于流的服务。
UDP则相反,提供不可靠、无连接、基于数据报的服务。UDP只会简单的通知应用程序发送失败。使用UDP协议的应用程序通常要自己处理书记确认、超时重传等逻辑。
SCTP协议是一种相对较新的传输层协议,为了传输电话信号而设计的。

1.1.4 应用层

应用层负责处理应用程序的逻辑。数据链路层、网络层和传输层负责处理网络通信细节,这部分必须既稳定又高效,因此它们都在内核空间中实现。而应用层则在用户空间实现,因为它负责处理众多逻辑,比如文件传输、名称查询和网络管理等。
如果应用层也在内核中实现,则会使内核变得非常庞大。当然,也有少数服务器程序是在内核中实现的,这样代码就无须在用户空间和内核空间来回切换(主要是数据的复制),极大地提高了工作效率。不过这种代码实现起来较复杂,不够灵活,且不便于移植。

应用层协议很多:
ping是应用程序而不是协议,它利用ICMP报文检测网络连接。
telnet协议是一种远程登录协议,它使我们能在本地完成远程任务,可以使用Telnet客户端登录到其他服务上。
OSPF(开放最短路径优先)协议是一种动态路由更新协议,用于路由器之间的通信,已告知对方各自的路由信息。
DNS(域名服务)协议提供机器域名到IP地址的转换

应用层协议(或程序)可能跳过传输层直接使用网络层提供的服务,比如ping程序和OSPF协议。应用层协议(或程序)通常既可以使用TCP服务,又可以使用UDP服务,比如DNS协议。我们可以通过/etc/services文件查看所有知名的应用层协议,以及它们都能使用哪些传输层服务。

1.2 封装

上层协议是如何使用下层协议提供的服务的呢?其实这是通过封装(encapsulation) 实现的。应用程序数据在发送到物理网络上之前,将沿着协议栈从上往下依次传递。每层协议都将在上层数据的基础上加上自己的头部信息(有时还包括尾部信息),以实现该层的功能,这个过程就称为封装

在这里插入图片描述
TCP

经过TCP封装后的数据称为TCP报文段(TCPmessagesegment),或者简称TCP段。前文提到,TCP协议为通信双方维持一个连接,并且在内核中存储相关数据。这部分数据中的TCP头部信息和TCP内核缓冲区(发送缓冲区或接收缓冲区)数据一起构成了TCP报文段。
当发送端应用程序使用send(或者write)函数向一个TCP连接写人数据时,内核中的TCP模块首先把这些数据复制到与该连接对应的TCP内核发送缓冲区中,然后TCP模块调用IP模块提供的服务,传递的参数包括TCP头部信息和TCP发送缓冲区中的数据,即TCP报文段。
在这里插入图片描述
UDP

当一个UDP数据报被成功发送之后,UDP 内核缓冲区中的该数据报就被丢弃了。如果应用程序检测到该数据报未能被接收端正确接收,并打算重发这个数据报,则应用程序需要重新从用户空间将该数据报拷贝到UDP内核发送缓冲区中。

IP

经过IP封装后的数据称为IP数据报(IP datagram)。IP数据报也包括头部信息和数据部分,其中数据部分就是一个TCP报文段、UDP数据报或者ICMP报文。


经过数据链路层封装的数据称为帧( frame)。传输媒介不同,帧的类型也不同。比如,以太网上传输的是以太网帧(ethermet frame),而令牌环网络上传输的则是令牌环帧(tokenring frame)。以以太网帧为例,其封装格式如下图:
在这里插入图片描述
帧的最大传输单元(Max Transmit Unit, MTU),即帧最多能携带多少上层协议数据(比如IP数据报),通常受到网络类型的限制。如图所示的以太网帧的MTU是1500字节。正因为如此,过长的IP数据报可能需要被分片(fragment)传输。

帧才是最终在物理网络上传送的字节序列。至此,封装的过程完成。

1.3 分用

当帧到达目的主机时,将沿着协议栈自底向上依次传递。各层协议依次处理帧中本层负责的头部数据,以获取所需的信息,并最终将处理后的帧交给目标应用程序。这个过程称为分用。分用是依靠头部信息中的类型字段实现的。
在这里插入图片描述
因为IP协议、ARP协议和RARP协议都使用帧传输数据,所以帧的头部需要提供某个字段(具体情况取决于帧的类型)来区分它们。以以太网帧为例,它使用2字节的类型字段来标识上层协议。如果主机接收到的以太网帧类型字段的值为0x800,则帧的数据部分为IP数据报。

同样,因为ICMP协议、TCP协议和UDP协议都使用IP协议,所以IP数据报的头部采用16位的协议字段来区分它们。

TCP报文段和UDP数据报则通过其头部中的16位的端口号字段来区分上层应用程序。比如DNS协议对应的端口号是53,HTTP协议(Hyper-Text TransferProtocol,超文本传送协议)对应的端口号是80。所有知名应用层协议使用的端口号都可在/etc/services文件中找到。

帧通过上述分用步骤后,最终将封装前的原始数据送至目标服务(上图中的ARP服务、RARP服务、ICMP服务或者应用程序)。这样,在顶层目标服务看来,封装和分用似乎没有发生过。

1.5 ARP协议工作原理

ARP协议能实现任意网络层地址到任意物理地址的转换,不过本书仅讨论从IP地址到以太网地址(MAC地址)的转换。
其工作原理是:主机向自己所在的网络广播一个ARP请求,该请求包含目标机器的网络地址。此网络上的其他机器都将收到这个请求,但只有被请求的目标机器会回应一个ARP应答,其中包含自己的物理地址。

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

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
ARP请求 / 应答报文长度为28字节,不过有的实现要求以太网帧数据部分长度至少为46字节,此时将增加一些填充字节,已满足需要,这时以太网帧长度为64字节。

1.5.2 ARP高速缓存的查看和修改

通常,ARP维护一个高速缓存,其中包含经常访问(比如网关地址)或最近访问的机器的IP地址到理地址的映射。这样就避免了重复的ARP请求,提高了发送数据包的速度。

Linux下可以使用arp命令查看和修改ARP高速缓存。(使用arp -a):
在这里插入图片描述

1.6 DNS工作原理

我们通常使用机器的域名来访问这台机器,而不直接使用其IP地址,比如访问因特网上的各种网站。DNS主要用途是将机器的域名解析成IP地址。

1.6.1 DNS查询和应答报文详解

DNS是一套分布式的域名服务系统。每个DNS服务器上都存放着大量的机器名和IP地址的映射,并且是动态更新的。众多网络客户端程序都使用DNS协议来向DNS服务器查询目标主机的IP地址。DNS查询和应答报文的格式如图所示:
在这里插入图片描述
16位标识字段用于标记一对DNS查询和应答,以此区分一个DNS应答是哪个DNS查询的回应。
16位标志字段用于写上具体的通信方式和返回通信状态。细节如下:
在这里插入图片描述
各标志的含义分别是:
在这里插入图片描述
接下来的4个字段。对查询报文而言,他一般包括1个查询问题,而其余的则为0。应答报文的应答资源记录数则至少为1。

查询问题格式:
在这里插入图片描述
查询名以一定的格式封装了要查询的主机域名。
查询类型表示如何执行查询操作,常见的类型如下:

  • A,值是1,表示获取目标主机IP地址
  • CNAME,值是5,表示获得目标主机的别名
  • PTR,值是12,表示反向查询

查询类通常为1,表示获取IP地址。

应答字段、授权字段、额外信息字段都是用资源记录格式。资源记录格式如下:
在这里插入图片描述

1.6.2 Linux下访问DNS服务

我们要访问DNS服务,就必须先知道DNS服务器的IP地址。Linux使用/etc/resolv.conf文件来存放DNS服务器的IP地址。机器ernest-laptop上,该文件的内容如下:
在这里插入图片描述
其中两个IP地址分别是首选DNS服务器地址和备选DNS服务器地址。

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

1.7 socket和TCP/IP协议族的关系

前文提到,数据链路层、网络层、传输层协议是在内核中实现的。因此操作系统需要实现一组系统调用,使得应用程序能够访问这些协议提供的服务。实现这组系统调用的API(Application Programming Interface,应用程序编程接口)主要有两套:socketXTI。XTI现在基本不再使用,本书仅讨论socket。

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

  1. 将应用程序数据从用户缓冲区中复制到TCP/UDP内核发送缓冲区,以交付内核来发送数据,或者是从内核TCP/UDP接收缓冲区中复制数据到用户缓冲区,以读取数据。
  2. 应用程序可以通过它们来修改内核中各层协议的某些头部信息或其他数据结构,从而精细地控制底层通信的行为。比如可以通过setsockopt函数来设置IP数据报在网络上的存活时间。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值