一个IP包分为包头(header)和数据(payload/data)两部分。报头是实现IP通信所必需的附加信息,数据是通过IP通信传输的信息。黄色区域(同名区域)我们看到有三个黄色区域跨越IPv4和IPv6。Version(4位)用于表示IP协议版本,是IPv4还是IPv6(IPv4,Version=0100;IPv6,Version=0110)。SourceAddress和DestinationAddress分别是源地址和目的地址的IP地址。蓝色区域(名称已更改的区域)生存时间(IPv6中的跳数限制)。TimetoLive最初表示一个IP包的最大生存时间:如果IP包在传输过程中超过了TimetoLive,则该IP包将失效。后来在IPv4的这个区域记录了一个整数(比如30),表示IP包中继过程中最多经过30个路由中继。如果超过30个路由中继,则IP数据包将失效。每次IP数据包通过路由器时,路由器都会从TimetoLive中减去1。当路由器发现TimetoLive为0时,它将不再发送IP数据包。IPv6中的HopLimit区域也记录了路由中继的最大数目,与IPv4的作用相同。TimetoLive/HopLimit避免了Internet中IP数据包的无限中继。服务类型服务类型(IPv6中的流量类别)。服务类型最初用于确定IP数据包的优先级。例如,语音通话需要实时性,因此其IP包的优先级应该高于Web服务IP包。然而,这个最初不错的想法并没有被微软采纳。Windows下产生的IP包具有相同的最高优先级,所以在当时Linux和Windows的混合网络中,Linux的IP传输会比Windows慢(只是因为Linux更守规矩!)。后来TypeofService实际上分为两部分:DifferentiatedServiceField(DS,前6位)和ExplicitCongestionNotification(ECN,后2位)。前者仍然用于区分服务类型,而后者则用于指示IP数据包所经过的路由的流量情况。IPv6的TrafficClass也分为两部分。通过IP包提供不同的服务,对服务进行不同的优化的想法由来已久,但具体的方法还没有形成公认的约定。例如,ECN区域用于指示IP数据包经过的路径的流量状态。如果接收方接收到的ECN区表明路径拥塞,则接收方应进行调整。但实际上,许多收件人忽略了ECN中包含的信息。流量状态控制通常由高层协议(如TCP)实现。协议协议(IPv6中的NextHeader)。Protocol是用来描述IP包的Payload部分所遵循的协议,即IP包上面的协议是什么。它显示了IP数据包中封装了什么样的高级协议数据包(TCP?UDP?)。红色区域(IPv6中删除的区域)我们来看一下IPv4和IPv6的长度信息。IPv4标头的长度。标题的末尾是选项。每个选项有32位,这是一个可选区域。IPv4标头可以根本没有选项字段。如果不考虑选项,整个IPv4头有20个字节(上面每行4个字节)。但是由于选项的存在,整个header的总长度是可变的。我们用IHL(InternetHeaderLength)记录包头的总长度,用TotalLength记录整个IP包的长度。IPv6没有选项,它的头部是固定长度的40字节,所以IPv6不需要IHL区域。PayloadLength用于表示IPv6数据部分的长度。整个IP包是40bytes+PayloadLength。IPv4中也有一个HeaderChecksum区域。此校验和用于验证IP数据包的标头信息。Checksum和小喇叭里面提到的CRC算法不一样。IPv6没有校验和区域。IPv6数据包的验证依赖于高层协议来完成,其优点是省去了执行校验和验证所需的时间,减少了网络延迟(latency)。Identification、flags和fragmentoffset,这三个包是针对分片(fragmentation)的。分片是指路由器将接收到的IP数据包拆分成多个IP数据包进行传输,接收到这些“分片”的路由器或主机需要将这些“分片”重新组合成一个IP数据包。不同的局域网支持不同的最大传输单元(MTU,MaximumTransportationUnit)。如果一个IP包的大小超过了局域网支持的MTU,进入局域网就需要分片(就好像面包太大了,必须掰碎才能放进碗里)。碎片化会给路由器和网络带来很大的负担。最好在发送IP包之前检测整条路径上的最小MTU,IP包的大小不要超过最小MTU,以免分片。IPv6旨在避免碎片化。每个IPv6LAN的MTU必须大于或等于1280字节。IPv6默认发送IP包大小为1280字节。PainfullyFragmentedGreenArea(IPv6NewArea)FlowLabel是IPv6中的一个新区域。它用于提醒路由器重用以前的中继路径。这样,IP数据包就可以自动维护出发时的顺序。这对于流媒体等应用程序很有帮助。Flow标签的进一步使用仍在开发中。“我正在尽力”的IP协议在创建时是一个松散的网络。这个网络是由各个大学的局域网相互连接而成,由一群偶遇的极客维护。因此,IP协议认为它的环境是不可靠的:路由器坏掉、实验室着火或博士踢电缆之类的事情随时可能发生。在不可靠的网络等危险环境中,IP协议提供的传输只能是“尽力而为”。所谓“我会尽力”的潜台词是,出了问题不要怪我,我只是承诺会尽力而为,并不能保证。因此,如果IP包在传输过程中出现错误(比如校验和不匹配,比如流量过大,比如超过TimetoLive),根据IP协议,你的IP包会被直接丢弃。游戏结束,将不再努力修复错误。尽最大努力使IP协议非常简单。更多的质量控制交给了高层协议,IP协议只负责高效传输。(多么不负责任的邮政系统)“效率优先”还体现在IP包的顺序上。即使源和目的地保持不变,IP协议也不保证IP数据包到达的顺序。我们已经知道IP中继是根据路由表来确定中继路由的。如果在不断发送IP包的过程中路由表发生了更新(比如出现了一条新的捷径),那么后面发送的IP包就会选择走不同的中继路由。如果新路径的传输速度更快,那么后面发送的IP包可能会先到达。就像在多车道的高速公路上,每辆车都在不停地变换车道,最终所有的车道都挤满了车。这允许最大限度地利用道路。“队列跳转”IPv6中的流标签可以建议路由器将一些IP数据包保留在同一中继路径上。但这只是一个“建议”,路由器可能会忽略它。标头校验和算法标头校验和区域有16位。这样得到,从header中得到除checksum之外的0/1序列,例如:91948073000040004011C0A80001C0A800C7(十六进制hex,这是为了演示操作过程而设计的header)根据Sixteenbits(即4个十六进制)将整个序列划分。除法后将每个4位十六进制累加相加。如果进位多于16位,将进位加到结果最后16位的最后一位:BinaryHex10010001100101009194+10000000011100118073----------------1000100100000011111207+1-----------------00010010000010001208上面的计算称为补码和。求所有十六位数字的和,补码sum(4500,0073,0000,4000,4011,C0A8,0001,C0A8,00C7)=1433然后,将1433的每一位取反(0->1,1->0),你得到校验和:EBCC,我们的包头是:91948073000040004011EBCCC0A80001C0A800C7收到IP包后,IP包的接收方可以求上面16位的补码和,应该得到FFFF.如果不是FFFF,则标头不正确,整个IP数据包将被丢弃。(再次提醒,例子中使用的IP头并不是真正的头,只是用来演示算法)总结每个网络协议的形成都有其历史原因。例如,IP协议用于连接各种分散的实验室网络。由于当时的网络很小,IPv4(IPv4产生于1970年代)的地址总数为40亿。尽管在当时被认为是一个庞大的数字,但数字浪潮很快带来了地址枯竭的危机。IPv6的主要目的是增加IPv4的地址容量,但同时根据新时代IPv4的经验和技术进步进行改进,比如避免分片,比如取消校验和(由于高级协议TCP)。网络协议在技术上并不复杂,更多的考虑是面向策略的。IP协议是“尽力而为”的,IP传输是不可靠的。但是这样的设计却达到了IP协议的效率。
