1、TCP/IP协议族体系结构及主要协议
现在Internet使用的主流协议族是TCP/IP协议族,它是一个分层、多协议的通信体系。 TCP/IP协议族是一个四层协议系统,自底而上分别是数据链路层、网络层、传输层和应用层。每一层完成不同的功能,且通过若干协议来实现,上层协议使用下层协议提供的服务,如下图所示:
1.1 数据链路层
数据链路层实现了网卡接口的网络驱动程序,以处理数据在物理媒介(比如以太网、令牌环等)上的传输。不同的物理网络具有不同的电气特性,网络驱动程序隐藏了这些细节,为上层协议提供一个统一的接口。 数据链路层两个常用的协议是ARP协议( Address Resolve Protocol,地址解析协议)和RARP协议(Reverse Address Resolve Protocol, 逆地址解析协议)。它们实现了IP地址和机器物理地址(通常是MAC地址,以太网、令牌环和802.11无线网络都使用MAC地址)之间的相互转换。 网络层使用IP地址寻址一台 机器,而数据链路层使用物理地址寻址一台机器,因此网络层必须先将目标机器的IP地址转化成其物理地址,才能使用数据链路层提供的服务,这就是ARP协议的用途。RARP 协议仅用于网络上的某些无盘工作站。因为缺乏存储设备,无盘工作站无法记住自己的IP地址,但它们可以利用网卡上的物理地址来向网络管理者(服务器或网络管理软件)查询自身的IP地址。运行RARP服务的网络管理者通常存有该网络上所有机器的物理地址到IP地址的映射。
1.2 网络层
网络层实现数据包的选路和转发。WAN (Wide Area Network,广域网)通常使用众多分级的路由器来连接分散的主机或LAN (Local Area Network,局域网),因此,通信的两台主机一般不是直接相连的,而是通过多个中间节点(路由器)连接的。网络层的任务就是选择这些中间节点,以确定两台主机之间的通信路径。同时,网络层对上层协议隐藏了网络拓扑连接的细节,使得在传输层和网络应用程序看来,通信的双方是直接相连的。 网络层最核心的协议是IP协议(Intermet Protocol,因特网协议)。IP 协议根据数据包的目的IP地址来决定如何投递它。如果数据包不能直接发送给目标主机,那么IP协议就为它寻找一个合适的下一跳(next hop)路由器,并将数据包交付给该路由器来转发。多次重复这一过程,数据包最终到达目标主机,或者由于发送失败而被丢弃。可见,IP 协议使用逐跳(hop by hop)的方式确定通信路径。 网络层另外一个重要的协议是ICMP协议(Internet Control Message Protocol,因特网控制报文协议)。它是IP协议的重要补充,主要用于检测网络连接。ICMP 协议使用的报文格式如下图所示。 上图中,8位类型字段用于区分报文类型。它将ICMP报文分为两大类: 一类是差错报文,这类报文主要用来回应网络错误,比如目标不可到达(类型值为3)和重定向(类型值为5);另一类是查询报文,这类报文用来查询网络信息,比如ping程序就是使用ICMP报文查看目标是否可到达(类型值为8)的。有的ICMP报文还使用8位代码字段来进一步细分不同的条件。比如重定向报文使用代码值0表示对网络重定向,代码值1表示对主机重定向。ICMP 报文使用16位校验和字段对整个报文(包括头部和内容部分)进行循环冗余校验(Cyclic Redundancy Check,CRC), 以检验报文在传输过程中是否损坏。不同的ICMP报文类型具有不同的正文内容。
需要指出的是,ICMP 协议并非严格意义上的网络层协议,因为它使用处于同一层的IP协议提供的服务(一般来说,上层协议使用下层协议提供的服务)。
1.3 传输层
传输层为两台主机上的应用程序提供端到端(end to end)的通信。与网络层使用的逐跳通信方式不同,传输层只关心通信的起始端和目的端,而不在乎数据包的中转过程。如下图展示了传输层和网络层的这种区别。 上图中,垂直的实线箭头表示TCP/IP协议族各层之间的实体通信(数据包确实是沿着这些线路传递的),而水平的虚线箭头表示逻辑通信线路。该图中还附带描述了不同物理网络的连接方法。可见,数据链路层(驱动程序)封装了物理网络的电气细节:网络层封装了网络连接的细节;传输层则为应用程序封装了一条端到端的逻辑通信链路,它负责数据的收发、链路的超时重连等。 传输层协议主要有三个: TCP 协议、UDP协议和SCTP协议。 TCP协议(Transmission Control Protocol,传输控制协议)为应用层提供可靠的、面向连接的和基于流(stream)的服务。TCP协议使用超时重传、数据确认等方式来确保数据包被正确地发送至目的端,因此TCP服务是可靠的。使用TCP协议通信的双方必须先建立TCP连接,并在内核中为该连接维持一些必要的数据结构,比如连接的状态、读写缓冲区,以及诸多定时器等。当通信结束时,双方必须关闭连接以释放这些内核数据。TCP服务是基于流的。基于流的数据没有边界(长度)限制,它源源不断地从通信的一端流人另一端。发送端可以逐个字节地向数据流中写人数据,接收端也可以逐个字节地将它们读出。 UDP协议(User Datagram Protocol,用户数据报协议)则与TCP协议完全相反,它为应用层提供不可靠、无连接和基于数据报的服务。“不可靠”意味着UDP协议无法保证数据从发送端正确地传送到目的端。如果数据在中途失,或者目的端通过数据校验发现数据错误而将其丢弃,则UDP协议只是简单地通知应用程序发送失败。因此,使用UDP协议的应用程序通常要自己处理数据确认、超时重传等逻辑。UDP协议是无连接的,即通信双方不保持一个长久的联系,因此应用程序每次发送数据都要明确指定接收端的地址(IP地址等信息)。基于数据报的服务,是相对基于流的服务而言的。每个UDP数据报都有一个长度,接收端必须以该长度为最小单位将其所有内容一次性读出,否则数据将被截断。 SCTP协议(Stream Control Transmission Protocol, 流控制传输协议)是一种相对较新的传输层协议,它是为了在因特网上传输电话信号而设计的。
1.4 应用层
应用层负责处理应用程序的逻辑。数据链路层、网络层和传输层负责处理网络通信细节,这部分必须既稳定又高效,因此它们都在内核空间中实现,如下图所示。而应用层则在用户空间实现,因为它负责处理众多逻辑,比如文件传输、名称查询和网络管理等。如果应用层也在内核中实现,则会使内核变得非常庞大。当然,也有少数服务器程序是在内核中实现的,这样代码就无须在用户空间和内核空间来回切换(主要是数据的复制),极大地提高了工作效率。不过这种代码实现起来较复杂,不够灵活,且不便于移植。
应用层协议很多,上图仅列举了其中的几个: ping是应用程序,而不是协议,前面说过它利用ICMP报文检测网络连接,是调试网络环境的必备工具。 telnet协议是一种远 程登录协议,它使我们能在本地完成远程任务,可以使用telnet客户端登录到其他服务器上。 OSPF (Open Shortest Path First,开放最短路径优先)协议是一种动态路由更新协议,用于路由器之间的通信,以告知对方各自的路由信息。 DNS (Domain Name Service,域名服务)协议提供机器域名到IP地址的转换。 应用层协议(或程序)可能跳过传输层直接使用网络层提供的服务,比如ping程序和OSPF协议。应用层协议(或程序)通常既可以使用TCP服务,又可以使用UDP服务,比如DNS协议。在Linux环境下,我们可以通过/etc/services文件查看所有知名的应用层协议,以及它们都能使用哪些传输层服务。
2、向下封装
上层协议是如何使用下层协议提供的服务的呢?其实这是通过封装(encapsulation) 实现的。应用程序数据在发送到物理网络上之前,将沿着协议栈从上往下依次传递。每层协议都将在上层数据的基础上加上自己的头部信息(有时还包括尾部信息),以实现该层的功能,这个过程就称为封装,如下图所示。 当发送端应用程序使用send (或者write)丽数向一个 TCP连接写人数据时,内核中的TCP模块首先把这些数据复制到与该连接对应的TCP内核发送缓冲区中,然后TCP模块调用IP模块提供的服务,传递的参数包括TCP头部信息和TCP发送缓冲区中的数据,即TCP报文段。 经过UDP封装后的数据称为UDP数据报(UDP datagram)。UDP对应用程序数据的封装与TCP类似。不同的是,UDP无须为应用层数据保存副本,因为它提供的服务是不可靠的。当一个UDP数据报被成功发送之后,UDP内核缓冲区中的该数据报就被丢弃了。如果应用程序检测到该数据报未能被接收端正确接收,并打算重发这个数据报,则应用程序需要重新从用户空间将该数据报拷贝到UDP内核发送缓冲区中。 经过IP封装后的数据称为IP数据报(IP datagram)。IP 数据报也包括头部信息和数据部分,其中数据部分就是一个TCP报文段、UDP数据报或者ICMP报文。 经过数据链路层封装的数据称为帧(frame)。 传输媒介不同,帧的类型也不同。比如,以太网上传输的是以太网帧(ethernet frame),而令牌环网络上传输的则是令牌环帧(token ring frame)。以以太网帧为例,其封装格式如下图所示。 以太网帧使用6字节的目的物理地址和6字节的源物理地址来表示通信的双方。关于类型(type)字段,我们将在后面讨论。4字节CRC字段对帧的其他部分提供循环冗余校验。 帧的最大传输单元(Max Transmit Unit, MTU),即帧最多能携带多少上层协议数据(比如IP数据报),通常受到网络类型的限制。图上所示的以太网帧的MTU是1500字节。正因为如此,过长的IP数据报可能需要被分片(fragment) 传输。
3、向上分用
当帧到达目的主机时,将沿着协议栈自底向上依次传递。各层协议依次处理帧中本层负责的头部数据,以获取所需的信息,并最终将处理后的帧交给目标应用程序。这个过程称为分用(demultiplexing)。 分用是依靠头部信息中的类型字段实现的。标准文档RFC 1700定义了所有标识上层协议的类型字段以及每个上层协议对应的数值。下图显示了以太网帧的分用过程。
因为IP协议、ARP 协议和RARP协议都使用帧传输数据,所以帧的头部需要提供某个字段(具体情况取决于帧的类型)来区分它们。以以太网帧为例,它使用2字节的类型字段来标识上层协议。如果主机接收到的以太网帧类型字段的值为0x800,则帧的数据部分为IP数据报,以太网驱动程序就将帧交付给IP模块;若类型字段的值为0x806,则帧的数据部分为ARP请求或应答报文,以太网驱动程序就将帧交付给ARP模块;若类型字段的值为0x835,则帧的数据部分为RARP请求或应答报文,以太网驱动程序就将帧交付给RARP模块。 同样,因为ICMP协议、TCP协议和UDP协议都使用IP协议,所以IP数据报的头部采用16位的协议(protocol) 字段来区分它们。 TCP报文段和UDP数据报则通过其头部中的16位的端口号(portnumber)字段来区分上层应用程序。比如DNS协议对应的端口号是53,HTTP 协议(Hyper-Text Transfer Protocol,超文本传送协议)对应的端口号是80。所有知名应用层协议使用的端口号都可在/etc/services文件中找到。 帧通过上述分用步骤后,最终将封装前的原始数据送至目标服务(上图中的ARP服务、RARP服务、ICMP 服务或者应用程序)。这样,在顶层目标服务看来,封装和分用似乎没有发生过。
|