Linux高性能服务器编程第一章TCP/IP协议族
Linux高性能服务器编程第一章TCP/IP协议族
Hoshea Zhang现在Internet(因特网)使用的主流协议族是TCP/IP协议族,它是一个分层、多协议的通信体系。本章简要讨论TCP/IP协议族各层包含的主要协议,以及它们之间是如何协作完成网络通信的。
TCP/IP协议族包含众多协议,我们无法一一讨论。本书将在后续章节详细讨论IP协议和TCP协议,因为它们对编写网络应用程序具有最直接的影响。本章则简单介绍其中几个相关协议:ICMP协议、ARP协议和 DNS协议,学习它们对于理解网络通信很有帮助。
TCP/IP协议族体系结构和主要协议
TCP/IP协议族是一个四层协议系统,自底而上分别是数据链路层,网络层,传输层和应用层,每一层完成不同的功能,通过若干协议来实现,上层协议使用下层协议提供的服务,如图所示:
数据链路层
常用协议是ARP协议和RARP协议,他们实现了IP地址和机器物理地址(通常是MAC地址)之间的互相转换
网络层使用IP地址寻址一台机器,而数据链路层使用物理地址寻址一台机器,因此网络层必须先将目标机器的IP地址转化为物理地址,才能使用数据链路层提供的服务,这就是ARP协议的用途。
网络层
网络层实现数据包的选路和转发。WAN(广域网)使用众多的分级的路由器来连接主机或者LAN(局域网),因此,通信的两台主机一般不是直接相连的,而是通过多个中间节点连接的。网络层的任务就是选择这些中间节点,来确定两台主机之间的通信路径。同时,网络层对上层协议隐藏了网络拓扑连接的细节,使得在传输层和网络应用程序看来,通信的双方是直接相连的。
网络层最核心的协议是IP协议,IP协议根据数据包的目的IP地址来决定如何投递它。如果数据包不能直接发送到目标主机,那么IP地址就为他寻找合适的下一跳路由器,并将数据包交付给这个路由器来转发。多次重复这一过程,数据包最终到达主机,或者因为发送失败而被丢弃。
网络层另外一个重要的协议是ICMP协议,他是IP协议的重要补充,主要用于检测网络连接,报文格式如下图所示:
八位类型字段用于区分报文类型,他将ICMP报文分为两大类,一类是差错报文,这类报文用来回应网络错误(比如目标不可达和重定向),另一类是查询报文,这类报文用来查询网络信息,比如ping程序就是用ICMP报文查看目标是否可到达。有的ICMP报文还使用八位代码字段进一步细分不同条件,比如重定向报文中使用代码值0表示对网络重定向,1表示对主机重定向。
ICMP报文还使用16位校验和对整个报文进行循环冗余校验。
传输层
传输层为两台主机上的应用程序提供端到端的服务,与网络层使用的逐跳通信方式不同,传输层只关心通信的起始端和目的端,而不在乎数据包的中转过程。
垂直的实现箭头表示TCP/IP协议族各层之间的实体通信,水平虚线箭头表示逻辑通信线路,由此可见数据链路层封装了物理网络的电气细节,传输层为应用程序封装了一条端到端的逻辑通信链路,网络层封装了网络连接的细节。
传输层的协议主要有三个:TCP协议、UDP协议和SCTP协议。
TCP协议
为应用层提供可靠的、面向连接的和基于流的服务。TCP协议使用超时重传、数据确认等方式来确保数据包被正确地发送至目的端,因此TCP服务都是可靠的。使用TCP协议通信的双方必须先建立TCP连接,并在内核中为该连接维持一些必要的数据结构,比如连接的状态、读写缓冲区以及诸多定时器等。
TCP的服务是基于流的,他没有边界限制,源源不断的从通信的一端到另一端
UDP协议
他为应用层提供不可靠无连接和基于数据报的服务,每个UDP都有一个长度,接收端必须以该长度为最小单位将其内容一次性读出,否则数据将被截断
SCTP协议
是一种相对较新的协议
应用层
应用层协议很多
- ping是应用程序,而不是协议,前面说过它利用ICMP报文检测网络连接,是调试网络环境的必备工具。
telnet协议是一种远程登录协议,它使我们能在本地完成远程任务,本书后续章节将会多次使用telnet客户端登录到其他服务上。 - OSPF (Open Shortest Path First,开放最短路径优先)协议是一种动态路由更新协议,用于路由器之间的通信,以告知对方各自的路由信息。
- DNS (Domain Name Service,域名服务)协议提供机器域名到IP地址的转换,我们将在后面简要介绍DNS协议。
应用层协议(或程序)可能跳过传输层直接使用网络层提供的服务,比如 ping 程序和OSPF协议。应用层协议(或程序)通常既可以使用TCP服务,又可以使用UDP服务,比如 DNS协议。我们可以通过letc/services文件查看所有知名的应用层协议,以及它们都能使用哪些传输层服务
封装
上层协议是如何使用下层协议提供的服务的呢?其实这是通过封装(encapsulation)实现的。应用程序数据在发送到物理网络上之前,将沿着协议栈从上往下依次传递。每层协议都将在上层数据的基础上加上自己的头部信息(有时还包括尾部信息),以实现该层的功能,这个过程就称为封装,如下图所示
经过TCP封装后的数据称为TCP报文段(TCP message segment),或者简称TCP段。前文提到,TCP协议为通信双方维持一个连接,并且在内核中存储相关数据。这部分数据中的TCP头部信息和TCP内核缓冲区(发送缓冲区或接收缓冲区)数据一起构成了TCP报文段,如下图中的虚线框所示。
分用
当帧到达目的主机时,将沿着协议栈自底向上依次传递。各层协议依次处理帧中本层负责的头部数据,以获取所需的信息,并最终将处理后的帧交给目标应用程序。这个过程称为分用(demultiplexing)。分用是依靠头部信息中的类型字段实现的。标准文档RFC 1700定义了所有标识上层协议的类型字段以及每个上层协议对应的数值。下图显示了以太网帧的分用过程。
因为IP协议、ARP协议和RARP协议都使用帧传输数据,所以帧的头部需要提供某个字段(具体情况取决于帧的类型〉来区分它们。以以太网帧为例,它使用2字节的类型字段来标识上层协议(见图1-6)。如果主机接收到的以太网帧类型字段的值为0x800,则帧的数据部分为IP数据报(见图1-4),以太网驱动程序就将帧交付给IP模块﹔若类型字段的值为0x806,则帧的数据部分为ARP请求或应答报文,以太网驱动程序就将帧交付给ARP模块﹔若类型字段的值为0x835,则帧的数据部分为RARP请求或应答报文,以太网驱动程序就将帧交付给RARP模块。
同样,因为ICMP协议、TCP协议和UDP协议都使用IP协议,所以P数据报的头部采用16位的协议( protocol)字段来区分它们。
TCP报文段和UDP数据报则通过其头部中的16位的端口号(port number)字段来区分上层应用程序。比如DNS协议对应的端口号是53,HTTP协议(Hyper-Text TransferProtocol,超文本传送协议)对应的端口号是80。所有知名应用层协议使用的端口号都可在/etc/services文件中找到。
帧通过上述分用步骤后,最终将封装前的原始数据送至目标服务。这样,在顶层目标服务看来,封装和分用似乎没有发生过。
ARP协议工作原理
ARP协议能实现任意网络层地址到任意物理地址的转换,不过本书仅讨论从IP地址到以太网地址(MAC地址)的转换。其工作原理是:主机向自己所在的网络广播一个ARP请求,该请求包含目标机器的网络地址。此网络上的其他机器都将收到这个请求,但只有被请求的目标机器会回应一个ARP应答,其中包含自己的物理地址。
以太网ARP请求/应答报文详解
ARP请求/应答报文的格式如下图所示:
具体介绍如下:
- 硬件类型字段定义物理地址的类型,值为1时表示MAC地址
- 协议类型字段表示要映射的协议地址类型,他的值为0x800时表示IP地址
- 硬件地址长度字段和协议地址长度字段,顾名思义,单位是字节,对MAC地址来说,其长度为6,对IP地址来说其长度为4
- 操作字段表示四种操作类型,即ARP请求、ARP应答、RARP请求和RARP应答
- 最后四个字段指定通信双方的以太网地址和IP地址,发送到填充除目的端以太网地址的其他三个字段,以构建ARP请求并发送,接收端发现该请求的目的端IP是自己,就把自己的以太网地址填进去,然后交换两个目的端地址和发送端地址,以构建ARP应答发送出去并返回
ARP高速缓存的查看和修改
Linux可以用arp命令来查看和修改ARP请求(arp-a)
DNS工作原理
DNS查询和应答报文详解
DNS是一套分布式的域名服务系统。每个DNS服务器上都存放着大量的机器名和IP地址的映射,并且是动态更新的。众多网络客户端程序都使用DNS协议来向DNS服务器查询目标主机的IP地址。
具体不详解了
Linux访问DNS服务
要访问DNS服务先要知道DNS服务的IP地址,该文件的内容如下:
linux下一个常用的访问DNS服务器的客户端程序是host,如下所示:
host命令使用DNS协议和DNS服务器通信,-t选项告诉DNS用什么查询类型,这里用的是A类型,即通过机器的域名获得其IP地址。
socket和TCP/IP协议族的关系
由socket定义的这一组API提供如下两点功能:一是将应用程序数据从用户缓冲区中复制到TCP/UDP内核发送缓冲区,以交付内核来发送数据,或者是从内核TCP/UDP接收缓冲区中复制数据到用户缓冲区,以读取数据﹔二是应用程序可以通过它们来修改内核中各层协议的某些头部信息或其他数据结构,从而精细地控制底层通信的行为。比如可以通过setsockopt函数来设置IP数据报在网络上的存活时间。