在这一节讲了IP协议的基本内容:包括IPv4提供的操作、数据报在IPv4下是怎么样的结构、数据报是怎样切片发送的、IPv4的编址方式有什么……IPv6在下一节讲网络层协议簇时细讲。

IPv4协议的具体定义:RFC 791

Internet的地址分类

  • 按地址层级

    • 物理上的网络地址:区分物理接口,同一个局域网,一跳可达,用于在单个物理网络内路由PDU

    • 网际网路地址:全球可达,地址数量跟接口数量相关,例如IP地址,用于在多个网络间路由PDU

    • 应用层地址:进程地址,即端口

  • 按地址范围

    • 全球地址:即在全球范围内独一无二用以区分host的地址,路由器允许有多个这种地址(还是看接口数量);
    • 网络附件地址:用来在特定的网络中区分设备,例如 MAC 地址或 ATM host 地址;
    • 端口地址:在host系统中独一无二,用来区分进程。
  • 按寻址方式

    • 单播地址(最常见的unicast MAC,IP)
    • 广播地址(全FF);
    • 多播地址(每天在家看电视看直播时,就有多播地址的应用:多个用户看cctv1,就发多播地址给这几个人)
    • 任意播地址(假设百度有一千个站点,不用在南京时记住南京的百度地址,在北京时记住北京的,只需要用任播地址就可以就近访问)

IP Operation

IP的操作大体上可以被划分为5种。

Routing

  • host和router都持有路由转发表。转发表指明了当前数据报要送达的下一个路由器,这个表既是静态的——可能存在不同的路由路线,又是动态的——需要对拥塞和错误进行灵活响应;

  • 路由需要用到的路由策略有:Distance vector, Link state, Path vector。在这里暂时不深入介绍;

  • 发送方可以指定路由为要遵循的路由器的顺序列表;

  • 路由器可以做到路由记录。

Datagram lifetime

数据报可能会因为环路而一直在传播,同时route需要基于先前的网络信息进行,还有TCP也需要基于数据报的生存周期来决定执行方式;所以我们需要设置数据报在网络中的生存周期——TTL(Time To Live)。

最简单的TTL有hop count(根据跳数来计时)。

Fragmentation and re-assembly

PS:下面有详细的介绍。

当数据报的长度超过了MTU(最大传输unit)时,需要对数据报进行切片发送,以及切片到达目的地时进行重组。早期做法为不做全球控制,让路由器有分片功能,切了就发送。

处理分片重组出错:利用重组超时机制,或者每个分片都加上一个TTL。

Error control

不监测传播过程。由于checksum检查或者TTL expired等事件发生,路由器需要通知src数据报“去了数据报天国”;用ICMP来返回错误信息,src的I网络层收到信息后同时需要通知高层。

Flow control

流控使路由器可以控制数据流入速率。路由器buffer满了路由器就丢弃新进来的包,同时给src发送”停止“通知(用ICMP)。

IPv4 Packet Structure

IPv4有很多blog都帮忙精读过了,所以也不在这写太多生产数据垃圾……想要仔细研究的话可以去看RFC 791原文,在这里中贴一点简要的图例,给自己简单复盘用:



在这里要注意的是,数据报在IPv4下的最大长度为65535个字节,包括头部字段和数据字段。

IP Fragmentation

并不是所有的链路层协议都能承载相同长度的网络层packet,有的协议能承载很大的数据报,有的则很小,如以太网帧最大比特长度为1500字节,而有的只能到576字节,这个最大承载数据量用最大传输单元MTU来表示。

所以MTU大大限制了上一层网络层datagram的长度。当路由器中某条出链路的MTU比当前要转发的IP datagram小时,IP datagram是无法一次性在这条出链路上成功传输的。解决办法就是把该IP datagram切片成多个小数据报,再经过链路层封装后进行传输。切片后的数据报被称为fragment

各个fragment送达destination后需要重新组装成原来的datagram,组装必须在datagram送到传输层前完成。

如果不在destination进行组装而是在路由器进行,会对路由器产生极大的负担,而且后面还有可能需要继续切片,复杂性极大。

组装任务通过识别IP datagram中的三个字段来完成:identificationflagsfragment offset

identification即标识号,是在host生成datagram时贴上去的,每生成一个值就加一,protocalsrc addrdest addridentification四个字段共同确定一个独一无二的datagram。

flags即标志位,由于IP服务是“尽力而为”的,所以不能确保所有fragment都能到达目的地;要让目的地确定接收已经完成(即使fragment没有全部到达,也要有一个机制让host确定已经收到了最后的一个fragment,结束漫长的等待),就将最后一个fragment的flags的MF位置为1,其余fragment的MF位为0

fragment offset即偏移字段,可以用来确定该fragment在原来的datagram的哪个位置,同时让dest host确定是否丢失了fragment。

一个直观的图例如下:

PS:有一个有意思的小问题:fragment再被切片会怎么样?

RFC 791对fragmentation操作的原文

IP Address

IP地址长度32位,可以划分为network部分和host部分(划分标准是不定的,看你划在第几位);在地址的分配上,是一个链路接口与一个IP地址相关联,而不是一个host或一个路由器。

在图中我们可以看到有三个“子网”,要注意的是子网含有的不只有host,还有路由器的接口,这其实意味着子网是按照接口来分的。RFC950中写了对“子网”(subnet)的定义:Internet Standard Subnetting Procedure。在这里,我们引入子网掩码(subnet mask)的概念。像绿色部分的子网,它的子网地址就是223.1.1.0/24,其中的24就是子网掩码,指示了高24位是network部分,是属于网络地址。

上周有一篇博文做了对IP编址的一些总结,就放在这里:20张图说清楚 IP 协议;里面讲了早期IP地址分配策略,包括classful addressing(分类编制方式)和现在使用的CIDR(无类别域间路由选择)。

CIDR

在CIDR分配策略中,子网寻址的概念被一般化:IP地址由子网掩码被划分成两个部分,形式为a.b.c.d/x,其中x指示了地址中的最高x位为network部分,也被称为前缀prefix

一个ISP可以被看成一组子网的集合——它可以给使用它服务的企业、高校等划分Intranet,这个过程被称为Hierarchical addressing(分层编址)。如下图所示:ISP手持最大的20位子网,然后剩下的12位可以供它任意分配,于是它又把20~23位分给了8个组织,组织可以利用后面的9位host部分自由分配给组织里面的主机。

采用CIDR的好处就是可以很方便地实现路由聚合。由于子网内部的host通常被分配一块连续的地址,即前缀相同,则当路由器转发一个datagram进来时,在转发表中就像上一节说的那样,仅仅需要考虑prefix即可。

要注意的是,后面的32-x位为host部分,这部分并不是有2^(32-x)个地址可以用——需要留出全0的地址作为子网地址,还有全1的地址用来做广播地址。

Classful addressing

分类编址方案将IP地址分为五类,详细的已有前人总结(上面的链接),在这里只放一些图示,用来给自己快速复盘:

A类地址:目前已经被全部瓜分

PS:A类地址中有一个很重要的回环地址:127.0.0.1,这里有较为详细的介绍。

B类地址:同样也被全部瓜分^^

C类地址:接近瓜分完毕

其实分类编制方案也可以用子网掩码的视角看待,如下图:

计网学习笔记七 IP protocol basic的更多相关文章

  1. Typescript 学习笔记七:泛型

    中文网:https://www.tslang.cn/ 官网:http://www.typescriptlang.org/ 目录: Typescript 学习笔记一:介绍.安装.编译 Typescrip ...

  2. go微服务框架kratos学习笔记七(kratos warden 负载均衡 balancer)

    目录 go微服务框架kratos学习笔记七(kratos warden 负载均衡 balancer) demo demo server demo client 池 dao service p2c ro ...

  3. (转)Qt Model/View 学习笔记 (七)——Delegate类

    Qt Model/View 学习笔记 (七) Delegate  类 概念 与MVC模式不同,model/view结构没有用于与用户交互的完全独立的组件.一般来讲, view负责把数据展示 给用户,也 ...

  4. Learning ROS for Robotics Programming Second Edition学习笔记(七) indigo PCL xtion pro live

    中文译著已经出版,详情请参考:http://blog.csdn.net/ZhangRelay/article/category/6506865 Learning ROS forRobotics Pro ...

  5. python3.4学习笔记(七) 学习网站博客推荐

    python3.4学习笔记(七) 学习网站博客推荐 深入 Python 3http://sebug.net/paper/books/dive-into-python3/<深入 Python 3& ...

  6. Go语言学习笔记七: 函数

    Go语言学习笔记七: 函数 Go语言有函数还有方法,神奇不.这有点像python了. 函数定义 func function_name( [parameter list] ) [return_types ...

  7. iOS 学习笔记七 【博爱手把手教你使用2016年gitHub Mac客户端】

    iOS 学习笔记七 [博爱手把手教你使用gitHub客户端] 第一步:首先下载git客户端 链接:https://desktop.github.com 第二步:fork 大神的代码[这里以我的代码为例 ...

  8. 【opencv学习笔记七】访问图像中的像素与图像亮度对比度调整

    今天我们来看一下如何访问图像的像素,以及如何改变图像的亮度与对比度. 在之前我们先来看一下图像矩阵数据的排列方式.我们以一个简单的矩阵来说明: 对单通道图像排列如下: 对于双通道图像排列如下: 那么对 ...

  9. Linux学习笔记(七) 查询系统

    1.查看命令 (1)man 可以使用 man 命令名称 命令查看某个命令的详细用法,其显示的内容如下: NAME:命令名称 SYNOPSIS:语法 DESCRIPTION:说明 OPTIONS:选项 ...

  10. Java IO学习笔记七:多路复用从单线程到多线程

    作者:Grey 原文地址:Java IO学习笔记七:多路复用从单线程到多线程 在前面提到的多路复用的服务端代码中, 我们在处理读数据的同时,也处理了写事件: public void readHandl ...

随机推荐

  1. vs2019 debug 出现: printf is ambiguous

    在vs中写c++代码时,莫名其妙出现:printf is ambiguous 的错误. 第一步,有设置std namespace 删除后再输入 using namespace std; 第二步.删除u ...

  2. CSS 常用样式-文字三属性

    颜色 color: 作用:给文字设置颜色. 属性名 k :color 属性值 v :颜色名.颜色值. 颜色名: 颜色名就是使用颜色的英文单词进行表示. 需要记忆一些最常用的颜色名: 更多的颜色名可以通 ...

  3. C语言初级阶段7——指针3

    C语言初级阶段7--指针3 指针数组:描述的是一个数组,存储的是指针 #include<stdio.h> void fun(int(*arr)[2]) { for (int i = 0; ...

  4. 接口自动化-requests环境安装(import requests模块引用失败问题)

    命名规范,可以避免低级问题 1. 命名最好是英文字符.下划线.数字三个组成. 2.项目(工程)名称.文件包名.模块名称等都应该是用英文开头,不能纯数字,(下划线开头的一般有特殊含义,不懂的话别乱用) ...

  5. js 全屏显示指定区域

    小猪最近使用vue开发项目的时候,需要实现将指定区域全拼展示的操作. 小猪选择使用js来实现,实现原理:使用requestFullscreen()方法将指定的dom元素在全屏模式下打开. 支持的部分浏 ...

  6. C数列或者C向量以及C矩阵

    #include <stdlib.h> #include <stdio.h> #define TP double #define UI unsigned short int # ...

  7. C++学习流程

    一.初级入门阶段 数据类型.变量.内存布局.指针基础: 字符串.一维数组.二维数组: 一级指针,二级指针,三级指针,N级指针概念,指针数组和数组指针: 结构体.文件的使用: 动态库的封装和设计: 函数 ...

  8. CentOS7 进入修复模式的办法

    有时候配置Centos文件修改错误会导致系统无法登录,可以通过修复模式进行单用户运行模式,进行修复. 具体操作如下: 1.重启服务器,在选择内核界面使用上下箭头移动 2.选择内核并按"e&q ...

  9. 简单的继承练习——疑问:私有属性在类的方法内调用时,有必要使用get,set方法嘛?

    要求: 创建一个Circle类,设置半径属性和返回面积的方法,在无参构造器中初始化半径值为1. 创建一个Cylinder类,继承Circle类,设置属性高和返回体积的方法,在无参构造器中初始化长度为1 ...

  10. jxg项目Day5-关于项目打包

    springboot项目中手动打包,加以下依赖: <parent> <artifactId>spring-boot-dependencies</artifactId> ...