3比特的优先级(PRECEDENCE)子域指明本数据报的优先级,允许发送方表示本数据报的重要程度。优先级的取值从0到7,0表示普通优先级,即表示网络控制优先级。优先级是由用户指定的,大多数主机和路由器软件对此都不予理睬,但这种思想却是十分重要的,因为它毕竟提供了一种手段,允许控制信息享受比一般数据更高的优先级。比如说,如果主机和路由器都服从优先级的话,则可以给拥塞控制信息赋予更高的优先级,从而实现不受拥
塞影响的拥塞控制算法。D、T、R、C位表示本数据报所期望的传输类型。当这些比特位取值为1时,D代表低时延(Delay)T代表高吞吐量(Throughput)R代表高可靠性(Reliability),C代表低开销。当然,上述三位只是用户的请求,因特网并不能保证提供所要求的传输,只是把它们作为路由选择时的参考。另外要注意的是,每种物理网络技术的时延、吞吐量、可靠性性能之间往往是此强彼弱的,用户应只指定它们中的一个,同时指定多个没有任何意义。2.5.5 标识符、标志和分片偏移量网络数据最终都是通过物理网络帧传输,IP数据报也不例外。在理想的情况下,整个数据报被封装在一个物理帧中传输时网络效率最高。但是,不同的物理网络技术上所采用的最大帧长是相异的,这个帧尺寸称作最大传输单元(Maximum Transfer Unit,MTU)。例如:10Mb/s以太网每帧最多可承载1500个字节,而在100Mb/s的FDDI环上承载就可以大到4470个字节。当数据报分组从一个MTU较大的网络经路由器中继到一个MTU较小的网络上时,由于分组过长,路由器就会要么拒绝中继,要么将数据报分片后再传送。分片通常在路由器中完成,而数据报重组由主机的IP协议软件完成。IP报头中的标识符(ident)、标志和分片偏移量(frag_and_flags)三个域用作分片和重组控制。标识符标识数据报发送时的先后顺序,每产生一个新数据报标识符增一,目的机用它来重编分片数据报。同一IP数据报分片后,标识符域不变。分片偏移量指在完整的数据报内该分片的偏移量,偏移量按8个字节为单位计算。标志域由3个比特位组成,第一位保留为0,如图2.l3所示。 0 1 2 ┌─┬──┬──┐ │0│DF│MF│ └─┴──┴──┘ 图2.13 标志中的各位DF位表示分组禁止被分片。如果DF位置1,路由器就会不加考虑地废弃超长分组,同时还会发送一个ICMP错误信息给这个分组的源站点。MF位表示分组片未完。如果MF位清0,此分片是IP数据报分组的最后一片。2.5.6 存活时间存活时间(ttl)设置了该数据报在因特网中允许存在的最大生存时间,该时间以秒为单位。每当产生一新的数据报时,就为它设置一个最大的生存时间。当数据报通过的主机和路由器对该数据报进行处理时,又减去消耗的时间。一旦时间小于等于0,便将该数据报从因特网中删除,并向信源机发回出错信息。路由器通常不知道物理网络上的传送时间,存活时间也只是一个数量级的概念,并不要求精确。因为精确的记时首先需要因特网中所有节点的时钟精确同步,这是很难做到的。有一些办法可以简化处理数据报且不需要同步时钟:第一,路由上的每个路由器处理报头时,从存活时间中减去一;第二,如果数据报在路由器中因等待服务被延迟,则从存活时间中减去等待的时间。为IP数据报设置存活时间的思想,保证了即使路由表不可靠而选择了一个循环路由,数据报都不会在因特网中无休止地流动。RFC建议存活时间的缺省设置值为64,而Windows 98和 Windows NT 4.0的用户使用的存活时间缺省值为128。2.5.7 协议序列号协议域表示IP数据报中数据的协议类型,如TCP、UDP、ICMP等。表2-1列出了IANA已分配的常见协议序列号。 表2-1 ━━━━━━┯━━━━━━━┯━━━━━━━━━━━━━━━━━━ 十进制编号│ 关键字 │ 协议名称 ──────┼───────┼────────────────── 0│ │保留 ──────┼───────┼────────────────── 1│ICMP │因特网控制报文协议 ──────┼───────┼────────────────── 2│IGMP │因特网组管理协议 ──────┼───────┼────────────────── 3│GGP │网关-网关协议 ──────┼───────┼────────────────── 4│IP │IP里的IP ──────┼───────┼────────────────── 5│ST │数据流 ──────┼───────┼────────────────── 6│TCP │传输控制协议 ──────┼───────┼────────────────── 8│EGP │外部网关协议 ──────┼───────┼────────────────── 17│UDP │用户数据报协议 ──────┼───────┼────────────────── 29│ISO-TP4│ISO传输协议类4 ──────┼───────┼────────────────── 41~60│ │未分配 ──────┼───────┼────────────────── 70│VISA │VISA协议 ──────┼───────┼────────────────── 80│ISO-IP │ISO网间协议(CLNP) ──────┼───────┼────────────────── 88│IGRP │内部网关协议 ──────┼───────┼────────────────── 89│OSPF │开放式最短路径优先协议 ──────┼───────┼────────────────── 99~254│ │未分配 ──────┼───────┼────────────────── 255│ │保留 ━━━━━━┷━━━━━━━┷━━━━━━━━━━━━━━━━━━2.5.8 报头校验和报头中的任何一个域发生传输错误都会产生很多无法预料的结果。比如:如果发送地址错误,就可能无法删除一个已经过期的分组以及重编不属于同一报文的分片。报头校验和(Checksum)就可以保护IP数据报不产生这类错误,确保报头的完整性。IP报头校验和的计算是先将校验和域置0,把报头看成一个16位的整数予列,对每个整数分别计算其二进制反码,相加后再对结果计算一次二进制反码而求得的,它常被简称为反码和的反码。2.5.9 源地址和目的地址源IP地址(sourceIP)和目的IP地址(destIP)域包含了数据报的原始发送方和最终接收方的32位的IP地址。数据包可能经过许多中间路由器,但是这两个地址域始终不变。2.5.10 IP选项目的IP地址后面的IP选项域是任选域,它的主要目的是用来装载特定的功能以便于网络测试和调试。在IP数据报中,选项是连续出现的,中间没有任何分隔符。每个选项包含一个选项码字节,后面可能跟有一个长度字节和该选项的一组字节数据。如图2.14所示,选项代码字节分成三个域。 0 1 2 3 4 5 6 7 ┌─┬───┬───────┐ │C│选项类│ 选项号 │ └─┴───┴───────┘ 图2.14 选项代码字节中的三个域路由器在对IP数据报分片时,如果拷贝标志位(C)置1,说明该选项应被拷贝到所有片中去;如果置0,则仅把该选项拷贝到第一个分片中。选项类和选项号指明选项的一般类型,并且给定了该类中的一个特殊选择。现在已经定义的有两个选项组:0是控制选项,2是调试和测量选项。在同一选项类里面,用选项号来标识选项。表2-2列出了RFC 791中已经定义的8种选项,并给出了它们的选项类和选项号,可以看出大多数选项都是用于控制目的。 表2.2 ━━━┯━━━┯━━┯━━━━━━━━━━━━━━━━━━━━━━ 选项类│选项号│长度│描述 ───┼───┼──┼────────────────────── 0 │ 0 │- │选项列表结束。该选项只占一个字节没有长度字节 ───┼───┼──┼────────────────────── 0 │ 1 │- │无操作。该选项只占一个字节,没有长度字节。 ───┼───┼──┼────────────────────── 0 │ 2 │11│安全和处理限制(用于军事目的) ───┼───┼──┼────────────────────── 0 │ 3 │可变│自由源路由。用来在一个指定路径为数据报选路 ───┼───┼──┼────────────────────── 0 │ 7 │可变│记录路由。用来跟踪IP数据报所采用的路由 ───┼───┼──┼────────────────────── 0 │ 8 │ 4│数据流标识符。已过时。 ───┼───┼──┼────────────────────── 0 │ 9 │可变│严格源路由。用来在指定路径上为数据报选路。 ───┼───┼──┼────────────────────── 2 │ 4 │可变│因特网时戳。用来记录路由上的时间戳 ━━━┷━━━┷━━┷━━━━━━━━━━━━━━━━━━━━━━2.6 校验和差错检验现在的通信系统实际上很少在传输错误。例如微小通信信道的误码率通常能达到每传输10兆字节少于1个字节的错误(10-7),光纤信道的误码率通常是低于10-9。但不管怎么说,传输差错总是存在,必须采取相应的措施检测差错确保数据的正确。为了检测差错,网络系统通常随数据发送一小部分附加信息。发送方从数据中计算附加信息,并且接收方进行同样的计算来核对结果。有一些比较常用的方法能有效地检测差错,比如奇偶校验(parity chedk)、累加和、循环冗余校验,TCP/IP协议中则采用“反码和的反码”的校验和方法。奇偶校验机制要求对每个发送的字符附加一个奇偶校验位(parity bit),使得这个字符中1的个数为偶数或奇数,这被分别称作偶校验或奇检验。累加和是对所有的数据按字节、字或双字对齐求字节、字或双字和,并且不记进位。循环冗余校验和反码和的校验相对来说要复杂些,下面分别给出了对应的代码。 /* 用于计算CRC-16的查找表 */ static short crctab[]= { 0x0000,0xC0C1,0xC181,0x0140,0xC301,0x03C0,0x0280,0xC241, 0xC601,0x06C0,0x0780,0xC741,0x0500,0xC5C1,0xC481,0x0440, 0xCC01,0x0CC0,0x0D80,0xCD41,0x0F00,0xCFC1,0xCE81,0x0E40, 0x0A00,0xCAC1,0xCB81,0x0B40,0xC901,0x09C0,0x0880,0xC841, 0xD801,0x18C0,0x1980,0xD941,0x1B00,0xDBC1,0xDA81,0x1A40, 0x1E00,0xDEC1,0xDF81,0x1F40,0xDD01,0x1DC0,0x1C80,0xDC41, 0x1400,0xD4C1,0xD581,0x1540,0xD701,0x17C0,0x1680,0xD641, 0xD201,0x12C0,0x1380,0xD341,0x1100,0xD1C1,0xD081,0x1040, 0xF001,0x30C0,0x3180,0xF141,0x3300,0xF3C1,0xF281,0x3240, 0x3600,0xF6C1,0xF781,0x3740,0xF501,0x35C0,0x3480,0xF441, 0x3C00,0xFCC1,0xFD81,0x3D40,0xFF01,0x3FC0,0x3E80,0xFE41, 0xFA01,0x3AC0,0x3B80,0xFB41,0x3900,0xF9C1,0xF881,0x3840, 0x2800,0xE8C1,0xE981,0x2940,0xEB01,0x2BC0,0x2A80,0xEA41, 0xEE01,0x2EC0,0x2F80,0xEF41,0x2D00,0xEDC1,0xEC81,0x2C40, 0xE401,0x24C0,0x2580,0xE541,0x2700,0xE7C1,0xE681,0x2640, 0x2200,0xE2C1,0xE381,0x2340,0xE101,0x21C0,0x2080,0xE041, 0xA001,0x60C0,0x6180,0xA141,0x6300,0xA3C1,0xA281,0x6240, 0x6600,0xA6C1,0xA781,0x6740,0xA501,0x65C0,0x6480,DxA441, 0x6C00,0xACC1,0xAD81,0x6D40,0xAF01,0x6FC0,0x6E80,0xAE41, 0xAA01,0x6AC0,0x6B80,0xAB41,0x6900,0xA9C1,0xA881,0x6840, 0x7800,0xB8C1,0xB981,0x7940,0xBB01,0x7BC0,0x7A80,0xBA41, 0xBE01,0x7EC0,0x7F80,0xBF41,0x7D00,0xBDC1,0xBC81,0x7C40, 0xB401,0x74C0,0x7580,0xB541,0x7700,0xB7C1,0xB681,0x7640, 0x7200,0xB2C1,0xB381,0x7340,0xB101,0x7lC0,0x7080,0xB041, 0x5000,0x90C1,0x9181,0x5140,0x9301,0x53C0,0x5280,0x9241, 0x9601,0x56C0,0x5780,0x9741,0x5500,0x95C1,0x9481,0x5440, 0x9C01,0x5CC0,0x5D80,0x9D41,0x5F00,0x9FC1,0x9E81,0x5E40, 0x5A00,0x9AC1,0x9B81,0x5B40,0x9901,0x59C0,0x5880,0x9841, 0x8801,0x48C0,0x4980,0x8941,0x4B00,0x8BC1,0x8A81,0x4A40, 0x4E00,0x8EC1,0x8F81,0x4F40,0x8D01,0x4DC0,0x4C80,0x8C41, 0x4400,0x84C1,0x8581,0x4540,0x8701,0x47C0,0x4680,0x8641, 0x8201,0x42C0,0x4380,0x8341,0x4100,0x8lC1,0x8081,0x4040 }; /*计算长度为len的buf缓冲区中字节的CRC-16校验和 * *返回的CRC-16校验和是字长型的无符号数 *crc是用于累计的CRC-16校验和 *buf是字节型的指针 *len是按字节buf的长度 */ int crcbuf(crc,len,buf) register int crc;/* running CRC value*/ register u_int len; register u_char *buf; { register u_int i; for(i=0;i crc = ((crc>>8)&0xff)^crctab[(crc^*buf++)&0xff]; return(crc); } /*计算反码和的反码 *返回字符长型的无符号数 *buffer是字长型的指针 *size是按字节计算的buffer的长度 */ unsigned short checksum(unsigned short *buffer,int size) { unsigned long cksum = 0; while(1 { cksum += *buffer++; size -= sizeof(USHORT); } if(0 cksum += *(UCHAR*)buffer; cksum = (cksum>>16) + (cksum&0xffff); cksum += (cksum>>16); return(unsigned shout)(~cksum); }2.7 网间控制报文ICMP)IP协议的目的比较明确,它只是尽力地、最快地传递数据到目的站点,因此很难诊断错误情况,必须通过另外的协议返回相应的信息。针对网间层的错误诊断、拥塞控制、路径控制和查询服务四大功能,ICMP提供相应的报文。例如:当一个分组无法到达目的站点或TTL超时后,路由器就会废除这个分组,同时向源站点返回一个目的站点不可达的ICMP报文;另外,当网络拥塞(congestion)时,路由器就会废除过载的分组,同时向源站点返回一个源站点抑制的报文。RFC 792中定义了ICMP协议。 如图2.15所示,ICMP报文是封装在IP数据报的数据区中发送的,因此并不能保证它的可靠性。为了避免重复报告所引起的“雪崩”现象,ICMP报文不再引发ICMP报文。 ┌──────┬───────┐ │ICMP头标│ICMP数据区│ICMP报文 └──────┴───────┘ ┌────┬──────────────┐ │IP头标│ IP数据区 │IP数据报 └────┴──────────────┘ 图2.15 ICMP报文的封装2.7.1 ICMP报文格式ICMP报文分成头标和数据区两部分,其中头标包含类型、代码和校验和三个域。ICMP报文格式如图2.16所示。 0 1 2 3 01234567890123456789012345678901 ┌───┬───┬───────┐ │ 类型│代码 │校验和 │ ├───┴───┴───────┤ │ 数据 │ ├───────────────┤ │ ··· │ └───────────────┘ 图2.16 ICMP报文格式计算校验和的算法与IP报头校验和的算法相同,也是16位二进制反码和的反码。但要注意的是,它是整个ICMP数据报的校验和而不仅仅是头标的校验和;类型域是一个单字节整数,它指出报文的类型;代码域也是一个单字节整数,它提供关于报文类型更进一步的信息。表2-3定义了15个ICMP报文类型。 0││12│ 3││12│ 4││12│ 5││12│ 8││12│ 9││12│10││12│11││12│