《TCP/IP详解》(卷1)读书笔记:03章:IP(网际协议)

3.1引言

        所有TCP,UDP,ICMP,IGMP数据都是以IP数据报的形式传输的,所以IP是TCP/IP协议族中最核心的协议。IP是“不可靠”和“无连接”的协议。你是不是会以为这个互联网怎么这么“不靠谱”。

(1)不可靠:它不保证IP数据报能成功到达目的地,如果传输过程中发生了错误,那么IP会直接丢弃该数据报,然后发送ICMP消息给信源端。

(2)无连接:IP并不维护任何关于后续数据报的状态信息。每个数据报之间相互独立。比如发送两个连续的数据报A和B,由于两者选择的通信的路径的不同可能B比A先到达。

        看到这里,貌似真的不靠谱。其实这种设计是有原因的。生活中我们接触到的另一个通信网络——电信网。当我们打电话的时候,中间环节提供的数据传递是可靠的。因为我们不能经常发生这种情况:比如你说一句话,没传过去,然后对方说“你再说一遍”。但是电信公司会为如此可靠的电信网付出巨大的代价。实际上当初美国国防部在设计世界上第一个网络ARPNET的时候,就曾为“谁去负责数据传输的可靠性”而产生分歧。一种意见是像电信网一样由通信网络来提供可靠性,另一种意见是由通信双方的主机来提供可靠性。当然历史证明,他们最终选择的是后者。这当然有资金方面的考虑,但是我们要知道的是这种选择一点问题都没有的,电信网之所以需要可靠的网络是因为通信两端是普通的电话,而不是像电脑那样的智能设备。

        当中间传输环节出了差错,我们智能的主机们可以及时发现并要求重新发送(比如TCP)。而即便你设计了中间环节可靠的通信网,但数据传输到目的主机里,在接下来的环节也难免会出乱子,所以还不如直接就不使用可靠的连接,出了差错统一管理。当TCP发现数据包不完整的时候,会要求重新发送。所以即便IP提供的数据是不可靠的,但是多发送几次依然出错的概率还是几乎为0。

3.2IP首部

《TCP/IP详解》(卷1)读书笔记:03章:IP(网际协议)

图片来自网络

        上图中“数据”以上是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-time),设置了数据报可以经过的最多路由器数。它指定了数据报的生存时间。它的初始值通常被设置为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位的整数倍,这是报头长度字段所要求的。

----------------------------------------------------------思维延伸-------------------------------------------------------------------

大端法与小端法

《TCP/IP详解》(卷1)读书笔记:03章:IP(网际协议)《TCP/IP详解》(卷1)读书笔记:03章:IP(网际协议)

                                                               (图片来自*

        大端法就是数据的低位字节放在内存的高地址处,小端法是数据的低位字节放在内存的低地址处。从图上看,一目了然。我们PC不同的处理器采用的存储方法一般不同。比如Intel的x86采用的是小端法,而IBM,以及Sun出产的处理器采用大端法。但是涉及到网路通信的时候是统一使用大端法来传递数据的,所以大端法也称为“网络字节序”。如果所使用机器是小端法存储的,那么系统会必会进行转换。许多人对于大小端法优劣的争论是很情绪化的。其实并没有任何技术原因可以证明两者孰优孰劣。

        “端”(endian)一词起源于《格列佛游记》。书中有一个故事:有一个国家发生政变,分裂为两个国家,并且连年征战。而整个事件的起因是一派人赞成吃鸡蛋的时候应该打破小的一端来吃,另一派则主张应该打破大的一端来吃。双方还纷纷著书立作来阐述各自的道理。这是一个讽刺意味的故事。后来网路协议的开创者Danny Cohen使用了“端”这一术语来代表网路字节序。我想他的目的是告诫大家不要无谓的争执。

-----------------------------------------------------------延伸结束--------------------------------------------------------------------

3.3IP路由的选择

        由TCP/IP的分层可知,IP转发接收自上层的数据报(TCP、UDP、ICMP、IGMP),或者转发接收自其下层的数据报(网络接口层)。IP层在内存中有一个路由表,每当收到一份数据报的时候,就会检查一次路由表。IP会检查收到的数据报目的IP地址是否为本机的IP地址之一(或本机广播IP地址)。如果是的话,就证明是发送给本机的,那么IP层就会根据数据报的IP首部的协议字段,来将其装发给上层的对应协议来处理。而如果目的IP不是本机的话,IP会做出两种选择:(1)IP层被设置为路由器,将数据报转发出去。(2)丢弃该数据报。
路由表中每一项都包含的信息:
(1)目的IP地址
(2)下一站(或下一跳)路由器的IP地址
(3)标志
(4)为数据报的传输指定一个网络接口
  IP路由的选择是逐跳地进行的,它并不知道任何到达目的的完整路径,它假定下一站路由器(与当前主机相连)会更加接近目的主机。
IP路由选择(搜索路由表)完成的功能
(1)寻找能与目的IP地址完全匹配的表目(网络号主机号都匹配)。
(2)寻找能与目的IP地址的网络号相匹配的表目。
(3)寻找标为“默认(default)”的表目。
        容易看出上述三个步骤的优先级从上到下依次降低。当上述三个步骤都不能满足时,就会像生成该数据报的应用程序返回“主机不可达”或“网络不可达”的错误。一个路由器通常指定的是一个网络,而不是单个主机,这样就能大大缩小路由表的规模。

3.4子网

子网编址

        通过前面几讲,我们知道网络上的每一台主机都有一个唯一标识的IP地址,就像我们的身份证号一样。但实际上,我们可以不把一个IP地址分给一个主机,而是分给一个网络,这样会极大的节省IP地址。这么多台主机使用同一个IP地址,大家或许会好奇不会冲突吗?正是为了解决这个冲突问题,所以引入了子网编址。

 

0-7位

8-15位

16-23位

24-32位

A类IP

网络号

24位主机号

B类IP

网络号

16位主机号

C类IP

网络号

8位主机号

        由图中可以看出A,B类IP地址为主机号分配了太多的空间,可容纳的的主机数分别为2^24-2和2^16-2(之所以减2是因为要去掉全为1和全为0的情况),即16777214和65534。而实际上人们不会为一个网络安排这么多的主机。所以我们可以把主机号分出几位出来给子网号,剩余的再作为主机号。另外C类IP也可以进行子网划分。
        

子网掩码

        要简单准确地表示子网划分情况,就需要用到子网掩码。以B类地址的子网划分过程为例:
例如:

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

用点分十进制来表示子网掩码就是:255.255.255.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

用点分十进制来表示子网掩码就是:255.255.255.192
        然后给定了IP地址和子网掩码,主机就可以确定IP数据报的目的地址:
(1)本子网上的主机
(2)本网络中其他子网中的主机
(3)其他网络上的主机

   3.5特殊情况IP地址

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广播

        上图中,0表示所有比特位都为0,-1表示所有比特位都为1。netid,subnetid,hostid表示所有比特位不全为0,也不全为1。可以把这个表看成三个部分:
蓝色部分:表示特殊的源地址,它的网络号全为0,不可能是目的IP地址。比如当主机使用BOOTP协议确定自己的IP地址时,这种地址只能作为初始化过程中的源地址出现。
绿色部分:表示特殊的回环地址(第二章有介绍),它表示源地址和目的地址都是本主机。
橘色部分:表示广播地址,它的主机号全为1。

3.6ifconfig命令

        ifconfig命令在引导时运行,配置主机上各个网络接口。【注意,这里指的是类Unix系统。而Windows下是ipconfig】由于拨号接口可能经常接通或挂断,所以每次接通或挂断时,这个命令都会运行一次。
        以笔者使用的ubuntu为例,在终端键入命令ifconfig -a
《TCP/IP详解》(卷1)读书笔记:03章:IP(网际协议)
        图中很容易分成三个部分,eth0,lo,wlan0。eth就是ethernet(以太网)的缩写,lo是lockback(回环地址)的缩写,wlan不用说,就是无线网了。当然这个参数 -a去掉也是没关系的。你也可以指定要显示的端口比如:
《TCP/IP详解》(卷1)读书笔记:03章:IP(网际协议)
        上面有一行UP BROADCAST RUNNING MUTICAST MTU:1500 。
接口状态
UP
显示接口的状态,包括当前与接口关联的所有标志。据此确定接口当前已初始化 (UP) 还是未初始化 (DOWN)。
广播状态
BROADCAST
指示接口支持 IPv4 广播。
传输状态
RUNNING
指示系统正在通过接口传输包。
多播状态
MULTICAST
显示接口支持多播传输。示例中的接口支持 IPv4 多播传输。
最大传输单元
MTU 1500
显示此接口的最大传输大小为1500 个八位字节(第二章已讲过)
         ifconfig -s效果同netstat -i(见下面)
         ifconfig同样支持TCP/IP以外的协议族。具体关于ifconfig的命令信息可以在终端键入 man ifconfig查看。

3.7netstat命令

        netstat也提供系统上的接口信息,参数 -i 打印接口信息,-n 打印IP地址。
《TCP/IP详解》(卷1)读书笔记:03章:IP(网际协议)
        因为-n要显示的东西太多。我们只需要显示前面几个就行了,所以再加一个less的管道操作 。即:netstat -i|less
《TCP/IP详解》(卷1)读书笔记:03章:IP(网际协议)
        可以看到前面几个tcp连接的ip地址。
其他的netstat命令参数:

-r

列出路由表

-a

列出所有的连接状态

-t

仅列出tcp的连接

-u

仅列出udp的连接

-l

仅列出所有在监听的服务器的网路状态

-p

列出PID 与程序名

-c

设置自动刷新的秒数


小结

        由于网络的飞速发展,网络的IP地址将会被人们耗尽,所以人们提出了最新版本的IP协议(IPV6),它用6个字节(48位)来表示IP地址。如今还处于IPv4到IPv6的过渡期。粗略地算一下2的48次方,等于:281474976710656.一共有15位!!!。有一个形象的比喻来形容它包含的地址之多:如果以后IPv6普及,那么地球上的每一粒沙子都能有自己的IP地址。

《TCP/IP详解》(卷1)读书笔记:03章:IP(网际协议)

上一篇:集成测试的“面子”和“里子”


下一篇:5位运动员参加了10米台跳水比赛,有人让他们预测比赛结果: