所有TCP,UDP,ICMP,IGMP数据都是以IP数据报的形式传输的,所以IP是TCP/IP协议族中最核心的协议。IP是“不可靠”和“无连接”的协议。你是不是会以为这个互联网怎么这么“不靠谱”。
(1)不可靠:它不保证IP数据报能成功到达目的地,如果传输过程中发生了错误,那么IP会直接丢弃该数据报,然后发送ICMP消息给信源端。
(2)无连接:IP并不维护任何关于后续数据报的状态信息。每个数据报之间相互独立。比如发送两个连续的数据报A和B,由于两者选择的通信的路径的不同可能B比A先到达。
看到这里,貌似真的不靠谱。其实这种设计是有原因的。生活中我们接触到的另一个通信网络——电信网。当我们打电话的时候,中间环节提供的数据传递是可靠的。因为我们不能经常发生这种情况:比如你说一句话,没传过去,然后对方说“你再说一遍”。但是电信公司会为如此可靠的电信网付出巨大的代价。实际上当初美国国防部在设计世界上第一个网络ARPNET的时候,就曾为“谁去负责数据传输的可靠性”而产生分歧。一种意见是像电信网一样由通信网络来提供可靠性,另一种意见是由通信双方的主机来提供可靠性。当然历史证明,他们最终选择的是后者。这当然有资金方面的考虑,但是我们要知道的是这种选择一点问题都没有的,电信网之所以需要可靠的网络是因为通信两端是普通的电话,而不是像电脑那样的智能设备。
当中间传输环节出了差错,我们智能的主机们可以及时发现并要求重新发送(比如TCP)。而即便你设计了中间环节可靠的通信网,但数据传输到目的主机里,在接下来的环节也难免会出乱子,所以还不如直接就不使用可靠的连接,出了差错统一管理。当TCP发现数据包不完整的时候,会要求重新发送。所以即便IP提供的数据是不可靠的,但是多发送几次依然出错的概率还是几乎为0。
(图片来自网络)
上图中“数据”以上是IP首部,一般占20个字节,其中选项是可选的,并不一定存在。数据的二进制最高位在左边记作0bit,最低位在右边记作31bit,这种传递方法被称作“大端法”。开头四位“版本”标记IP协议的版本,现在常用的是版本4(IPV4)。后面的报头长度(首部长度)很好理解了,普通IP数据报字段值是5。因为首部长度一般是32位。
图中的服务级别通常叫做服务类型(TOS)。TOS字段共有8位,其中3位表示优先权(现在已被忽略),4位分别表示最小时延、最大吞吐量、最高可靠性和最小费用,剩余1位为未用位但必须置0。前面说的那4位只能置其中一位为1,其余为0.如果4位都是0则表示一般服务。
应用程序 |
最小时延 |
最大吞吐量 |
最高可靠性 |
最小费用 |
16进制值 |
Telnet/Rlogin |
1 |
0 |
0 |
0 |
0x10 |
FTP 控制 数据 任意数据块 |
|
||||
1 |
0 |
0 |
0 |
0x10 |
|
0 |
1 |
0 |
0 |
0x08 |
|
0 |
1 |
0 |
0 |
0x08 |
|
TFTP |
1 |
0 |
0 |
0 |
0x10 |
SMTP 命令阶段 数据阶段 |
|
||||
1 |
0 |
0 |
0 |
0x10 |
|
0 |
1 |
0 |
0 |
0x08 |
|
DNS UDP查询 TCP查询 区域传输 |
|
||||
1 |
0 |
0 |
0 |
0x10 |
|
0 |
0 |
0 |
0 |
0x00 |
|
0 |
1 |
0 |
0 |
0x08 |
|
ICMP 差错 查询 任何IGP |
|
||||
0 |
0 |
0 |
0 |
0x00 |
|
0 |
0 |
0 |
0 |
0x00 |
|
0 |
0 |
1 |
0 |
0x04 |
|
SNMP |
0 |
0 |
1 |
0 |
0x04 |
BOOTP |
0 |
0 |
0 |
0 |
0x00 |
NNTP |
0 |
0 |
0 |
1 |
0x02 |
Telnet和Rlogin是交互应用要求最小时延,而FTP用于文件传输,要求最大吞吐量,最高可靠性被指明给SNMP(网络管理协议)和路由选择协议。NNTP(用户网络新闻)是唯一要求最小费用的应用。不过不幸的是现在大多数TCP/IP实现都不支持TOS字段。
报文长度字段是指整个IP数据报的长度,我们根据报头长度和报文长度就能得出数据报中数据内容的起始位置和长度了。由于IP的报文长度字段是16位,所以一个IP数据报的最大长度是65535字节(2的16次方)。但是大多数的链路层都会进一步对IP数据报进行分片,因为主机要求不超过576自己的数据报,尽管有此限制,不过如今的大多数实现(比如网络文件系统NFS)是允许超过8192字节的。
标识字段标识主机发送的每一份数据报,每发送一个其值就会加1。而标识字段和片偏移字段以后在讲分片时我们再讨论。
生存时间字段简称TTL(time-to-live),设置了数据报可以经过的最多路由器数。它指定了数据报的生存时间。它的初始值通常被设置为32或64,每经过一个路由器,它的值就会减1。所以当其值为0时,该数据报就会被废弃,并发送ICMP通知源主机。
协议字段在第一章已经讲过。
首部检验和字段计算的是IP的首部,而不是后面的数据(而ICMP、IGMP、UDP和TCP的说不中均含有同时覆盖首部和数据的检验和码)。计算过程如下:
(1)将检验和字段置0
(2)对首部对每16位(2字节)进行二进制反码求和。将首部每16位看作一个整体。反码求和的意思是先对每16位求和,再将得到的和转为反码。
(3)当收到一份数据报时也要进行步骤(2)。如果计算结果应该全为1.若不全为1,则表示出错,IP会丢弃该数据报。
具体请移步这篇博客《IP首部检验和计算》。
每一份IP数据报都包含源IP地址和目的IP地址。最后一个字段是任选项,里面可以包含一些可选信息,但是已经很少被使用。在必要时会插入值为0的填充字节,来确保IP首部是32位的整数倍,这是报头长度字段所要求的。
----------------------------------------------------------思维延伸-------------------------------------------------------------------
(图片来自维基百科)
大端法就是数据的低位字节放在内存的高地址处,小端法是数据的低位字节放在内存的低地址处。从图上看,一目了然。我们PC不同的处理器采用的存储方法一般不同。比如Intel的x86采用的是小端法,而IBM,以及Sun出产的处理器采用大端法。但是涉及到网路通信的时候是统一使用大端法来传递数据的,所以大端法也称为“网络字节序”。如果所使用机器是小端法存储的,那么系统会必会进行转换。许多人对于大小端法优劣的争论是很情绪化的。其实并没有任何技术原因可以证明两者孰优孰劣。
“端”(endian)一词起源于《格列佛游记》。书中有一个故事:有一个国家发生政变,分裂为两个国家,并且连年征战。而整个事件的起因是一派人赞成吃鸡蛋的时候应该打破小的一端来吃,另一派则主张应该打破大的一端来吃。双方还纷纷著书立作来阐述各自的道理。这是一个讽刺意味的故事。后来网路协议的开创者Danny Cohen使用了“端”这一术语来代表网路字节序。我想他的目的是告诫大家不要无谓的争执。
-----------------------------------------------------------延伸结束--------------------------------------------------------------------
|
0-7位 |
8-15位 |
16-23位 |
24-32位 |
A类IP |
网络号 |
24位主机号 |
||
B类IP |
网络号 |
16位主机号 |
||
C类IP |
网络号 |
8位主机号 |
B类IP |
网络号 |
子网号(8位) |
主机号(8位) |
|
子网掩码 |
1 1 1 1 1 1 1 1 |
1 1 1 1 1 1 1 1 |
1 1 1 1 1 1 1 1 |
0 0 0 0 0 0 0 0 |
B类IP |
网络号 |
子网号(10位) |
主机号(6位) |
|
子网掩码 |
1 1 1 1 1 1 1 1 |
1 1 1 1 1 1 1 1 |
1 1 1 1 1 1 1 1 1 1 |
0 0 0 0 0 0 |
IP地址 |
可以为 |
描述 |
|||
网络号 |
子网号 |
主机号 |
源端 |
目的端 |
|
0 |
|
0 |
OK |
不可能 |
网路上的主机 |
0 |
|
hostid |
OK |
不可能 |
网路上特定的主机 |
127 |
|
任何值 |
OK |
OK |
回环地址 |
-1 |
|
-1 |
不可能 |
OK |
受限的广播(永远不被转发) |
netid |
|
-1 |
不可能 |
OK |
以网络为目的,向netid广播 |
netid |
subnetid |
-1 |
不可能 |
OK |
以子网为目的,向netid、subnetid广播 |
netid |
-1 |
-1 |
不可能 |
OK |
以所有子网为目的,向netid广播 |
接口状态
|
UP
|
显示接口的状态,包括当前与接口关联的所有标志。据此确定接口当前已初始化 ( UP) 还是未初始化 ( DOWN)。
|
广播状态
|
BROADCAST
|
指示接口支持 IPv4 广播。
|
传输状态
|
RUNNING
|
指示系统正在通过接口传输包。
|
多播状态
|
MULTICAST
|
显示接口支持多播传输。示例中的接口支持 IPv4 多播传输。
|
最大传输单元
|
MTU 1500
|
显示此接口的最大传输大小为1500 个八位字节(第二章已讲过)
|
-r |
列出路由表 |
-a |
列出所有的连接状态 |
-t |
仅列出tcp的连接 |
-u |
仅列出udp的连接 |
-l |
仅列出所有在监听的服务器的网路状态 |
-p |
列出PID与程序名 |
-c |
设置自动刷新的秒数 |