0%

IPv4和IPv6的详细介绍

互联网协议版本4(IPv4)和互联网协议版本6(IPv6)是两种主要的互联网协议,用于在计算机网络中标识和寻址设备。它们各自具有不同的特点和功能。在本文中,我们将对IPv4和IPv6进行详细介绍。

IPv4

IPv4是当前最常用的互联网协议,它于1981年发布,并在全球范围内得到广泛应用。IPv4使用32位地址来唯一标识连接到互联网的设备。这允许分配大约42亿个唯一的IP地址。

IPv4地址由4个十进制数组成,每个数之间用点号分隔,取值范围为0到255。例如,192.168.0.1是一个IPv4地址。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import socket

def is_ipv4(ip_address):
try:
socket.inet_pton(socket.AF_INET, ip_address)
return True
except socket.error:
pass

parts = ip_address.split('.')
if len(parts) != 4:
return False
for part in parts:
if not 0 <= int(part) <= 255:
return False

return True

IPv4协议定义了各种功能,包括数据包路由、错误检测和纠正、数据包分组和传输等。它使用TCP(传输控制协议)和UDP(用户数据报协议)等协议来提供可靠的数据传输服务。

然而,由于IPv4地址的有限性和增长的需求,IPv4地址分配已经接近枯竭。因此,IPv6的开发变得更加重要。

IPv6

IPv6是IPv4的下一代互联网协议,于1998年发布。与IPv4不同,IPv6使用128位地址来唯一标识设备,提供了比IPv4更大的地址空间。实际上,IPv6地址空间的大小是IPv4地址空间的340万亿亿亿倍。

IPv6地址由8组四位的十六进制数表示,每个组用冒号分隔。例如,2001:0db8:85a3:0000:0000:8a2e:0370:7334是一个IPv6地址。

1
2
3
4
5
6
7
8
9
10
import socket

def is_ipv6(ip_address):
try:
socket.inet_pton(socket.AF_INET6, ip_address)
return True
except socket.error:
pass

return False

默认地址

::1:表示本地主机的回环地址
2002::/16:表示移动IPv6地址
2001:0DB8::/32:表示文档RFC 3849中定义的临时链路本地地址
FE80::/10:表示链路本地地址
FF00::/8:表示多播地址
FF02::1:表示多播路由器(MR)地址
FF02::2:表示多播监听器(ML)地址

地址分类

IPv6地址分为以下几种类型:

全局地址:全局地址是指分配给全球的地址,它由两部分组成,前一部分为前缀,后一部分为后缀。前缀是指地址的前面部分,后缀是指地址的后面部分。

私有地址:私有地址是指分配给局域网的地址,它由两部分组成,前一部分为前缀,后一部分为后缀。前缀是指地址的前面部分,后缀是指地址的后面部分。

链接本地地址:链接本地地址是指分配给局域网内的设备的地址,它由两部分组成,前一部分为前缀,后一部分为后缀。前缀是指地址的前面部分,后缀是指地址的后面部分。

唯一本地地址:唯一本地地址是指分配给局域网内的设备的地址,它由两部分组成,前一部分为前缀,后一部分为后缀。前缀是指地址的前面部分,后缀是指地址的后面部分。

地址分配

IPv6地址的分配采用了一种基于时间的分配方案。在IPv6地址中,前8位表示

与IPv4相比,IPv6引入了许多新的功能和改进,包括:

地址自动配置:IPv6设备可以自动配置自己的IP地址,减少了手动配置的复杂性。
包头压缩:IPv6包头比IPv4包头小,可以提高网络性能。
流标签:IPv6支持流标签,可以根据不同的需求对数据流进行区分和管理。
简化头:IPv6头中不再包含一些IPv4中必需的选项,使得协议更加简单。
转换和过渡
由于IPv6是IPv4的下一代协议,设备和网络需要进行转换和过渡才能完全采用IPv6。一些转换技术包括:

双栈技术:同时支持IPv4和IPv6协议栈,可以在IPv4和IPv6之间进行通信。
仅IPv6:仅使用IPv6协议栈,完全放弃IPv4。
NAT64:将IPv6地址转换为IPv4地址,使得IPv4设备可以与IPv6网络通信。
总之,IPv4和IPv6是两种主要的互联网协议,它们各自具有不同的特点和功能。虽然IPv4仍然广泛使用,但IPv6的开发和采用已经成为未来的趋势。

再黑的夜总会迎来黎明
就算是睛空突然转阴
也还比黑夜更加明亮

关于目标

  • 目标不要随时变化
  • 目标不要超越自我,比如一个亿的小目标对于普通人来说就是扯蛋
  • 目标不要超过一年以上
  • 目标一定要有时间期限

关于计划

  • 计划一定是以目标为基础设定的
  • 计划一定要有里程碑,这里的里程碑就是一个大目标中的小目标
  • 计划一定要有时间上有限制
  • 计划一定会有变化,要及时调整
  • 当别人想让你改变计划时,要问自己值不值

关于执行

  • 事情要做的时候要马上去做,做到了要给自己一个正向的反馈
  • 每天看看自己做了什么,要把明天的事情写出来
  • 停止焦虑
  • 简单的事情更容易执行,
  • 固定的时间做固定的事情更容易坚持
  • 付出很少的事情更容易执行
  • 付出能得到反馈(奖励)的事情更容易坚持

关于自己

  • 永远不要担心自己会都没有做,而要为自己已经做过的事情自豪
  • 永远坚持自己的想法,不要让别人左右你的生活
  • 永完坚持给自已正向的反馈,忽略别人负面信息

商业模式

不太合适的一张图

图像

1
一个很重要的问题引发了我的思考:为什么人们喜欢用特定的软件,而不直接使用具备图灵完备性的Excel?

软件的核心是流程,虽然Excel 功能强大,但过于复杂,更多是非常模块化、原子化的组件,无法呈现特定领域的业务知识,使用具有一定门槛;而软件带有诸多事件按钮,是由程序加上软件工程构建出来的,即通过用户故事地图,将程序进行一系列的排列组合,以实现业务目的,它的一个进步性便体现在更加智能与体验友好(符合用户直觉),简化操作的同时,又具备程序能力。

我们发现软件其实与人的操作习惯、思考方式息息相关。SaaS (“软件即服务”)是卖给企业的,于是企业整个管理流程、业务流程与SaaS 软件便融为了一体。好的SaaS 软件能够让任何一个不懂这个行业的小白知道某件事件该怎么处理、数据该怎么分析、客户该如何管理、流程该如何设置等等,即好的SaaS 软件是提供了咨询服务能力的,而不是囿于像Excel 般功能迭代却忽视用户体验。

SaaS = 软件+商业模式,SaaS 的商业本质是业务管理的沉淀,诸如CRM 是定义管理程序的最佳实践、MA 是定义管理线索的最佳实践、HR SaaS 是定义管理员工的最佳实践,Authing 提供的身份云是管理员工和用户身份的最佳实践

但世界上没有一片叶子是相同的,受限于企业的业务形态与人才构成,每家公司的管理哲学都是不一致的。越是与业务紧耦合的SaaS,管理哲学越不一致,也就越需要PaaS。我们都知道Salesforce 做了大量的PaaS 来赋能客户的定制化业务,身份其实也是。我们从一线客户了解到,中国不是不接受产品化,而是缺少好产品,尤其在身份领域,缺少体验好、能帮助客户加快上线时间的身份PaaS 。

径莫便于捷,而又莫妙于迂。凡有故作迂途,以取别致者,必另开耳门一扇,以便家人之奔走。急则开之,缓则闭之,斯雅俗俱利,而理致兼收矣。

这是李渔在《闲情偶记》居家部中说明家中路径设置的一段话。看到这段话想到人的一生何不如此!!!

Jetpack 是什么

Jetpack 包含了一系列的 Android 库,这些库都采用了最佳做法并在 Android 应用中提供向后兼容。Jetpack 库在 androidx 命名空间发布。

Jetpack 使用

在 settings.gradle 文件中,将 google() 代码库添加到 dependencyResolutionManagement { repositories {…}} 块中

1
2
3
4
5
6
7
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google()
jcenter()
}
}

然后,在模块 build.gradle 文件中添加 Jetpack 组件,例如:

1
2
3
4
5
6
7
dependencies {
def lifecycle_version = "2.2.0"

implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version"
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"
...
}

Jetpack 组件

主要的组件有:

Jetpack 应用架构

界面层

界面层的作用是在屏幕上显示应用数据。接收用户的输入或外部输入(网络)来响应并更新界面的显示。
界面层主要有以下两部分组成:

  • 在屏幕上呈现数据的界面元素。—View
  • 用于存储数据,向界面元素提供数据以及处理逻辑的状态容器.— ViewModel

数据屋

应用的数据屋包含业务逻辑。业务逻辑决定应用的价值,它包含决定应用如何创建、存储和更改数据的规则。
数据支有多个库组成,每个库可包含多个数据源。你应该为应用处理的每种不同类型 的数据创建一个库类。
库类主要负责以下任务:

  • 向应用的提供数据
  • 对数据进行集中更改
  • 解决多个数据源之间的冲突
  • 从应用的其余部分提取数据
  • 包含业务逻辑

每个数据源类应仅负责处理一个数据源,访数据源可能是文件、网络来源或是本地数据库。

网域层

网域层负责封装复杂的业务逻辑,或者由多个 ViewModel 重复使用的简单业务逻辑。

最佳实践

  • 不要将数据存储在应用组件中
  • 减少对 Android 类的依赖
  • 在应用的各个模块之间设定明确定义的职责界限
  • 尽量少公开每个模块中的代码
  • 专注于应用的独特核心
  • 考虑如何使应用中的每个部分可以独立测试
  • 保留尽可能多的相关数据和最新的数据

Jetpack 和 AndroidX

androidx 命令空间包含 Android Jectpack 库。与支持库一样, androidx 命令空间中的库与 Android 平台分开提供,并向后兼容 Android 各个版本。

AndroidX 对原始的 Android 支持库进行了重大改进,支持库现已不做维护,不仅提供与支持库相同的功能,而且还提供了新的库。

AndroidX 包含以下功能:

  • AndroidX 中的所有软件包使用一致的命令空间 androidx。支持库软件包已映射到对应的 androidx.* 软件包。
  • 与支持库不同, andoridx 软件包会单独维护和更新。
  • 版本28.0.0是支持库的最后一个版本。

AndroidX 迁移

使用 Android Studio 3.2 及更高版本,您只需从菜单栏中依次选择 Refactor > Migrate to AndroidX,即可将现有项目迁移到 AndroidX。

重构命令使用两个标记。默认情况下,这两个标记在 gradle.properties 文件中都设为 true:

android.useAndroidX=true

Android 插件会使用对应的 AndroidX 库而非支持库。

android.enableJetifier=true

Android 插件会通过重写现有第三方库的二进制文件,自动将这些库迁移为使用 AndroidX。

在处理网络协议等一些二进制数据时,一般都是 C 或 C++ 擅长的领域,怎么在 swift 方便的读取二进制的信息呢?

定义

1
2
3
4
5
6
7
8
public struct Payload {
// 保存当前位置
public var pos: Int

// 保存二进制数据
var data: Data

}

固定长度数值的读取方法

1
2
3
4
5
6
7
8
9
mutating func read<T: FixedWidthInteger>(_ type: T.Type) -> T {
let size = MemoryLayout<T>.size

let value = self.data[self.pos...size].withUnsafeBytes({ p -> T in
return p.load(as: T.self).bigEndian
})
self.pos += size
return value
}

固定长度数值的写入方法

1
2
3
4
5
6
mutating func write<T: FixedWidthInteger>(_ value: T) {
var source = value.littleEndian
let d = Data(bytes: &source, count: MemoryLayout<T>.size)
self.data.append(d)
}

JSON数据在传输的时候需要先进行编解码。在python语言中常用标准库中的json库进行编解码工作,json可以方便的将JSON字符串解码成python中的基本数据类型,也可以将基本数据类型编码成JSON字符串进行传输,非常方便使用。

编码

编码通过 dump 和 dumps 两个函数可以编码。

dump

将基本的数据类型编码为JSON字符串。

函数声明

1
2
3
def dump(obj, skipkeys=False, ensure_ascii=True, check_circular=True,
allow_nan=True, cls=None, indent=None, separators=None,
default=None, sort_keys=False, **kw)

常用参数

  • skipkeys: 默认值是False,如果dict的keys内的数据不是python的基本类型,设置为False时,就会报TypeError的错误。此时设置成True,则会跳过这类key
  • ensure_ascii:默认值True,如果dict内含有non-ASCII的字符,则会类似\uXXXX的显示数据,设置成False后,就能正常显示
  • indent:应该是一个非负的整型,如果是0,或者为空,则一行显示数据,否则会换行且按照indent的数量显示前面的空白
  • separators:分隔符,实际上是(item_separator, dict_separator)的一个元组,默认的就是(‘,’,’:’);这表示dictionary内keys之间用“,”隔开,而KEY和value之间用“:”隔开。
  • sort_keys:将数据根据keys的值进行排序。

例子1

1
2
3
4
5
import json

dic1 = {'name': "Paris", 'population': 2243}
json_dic = json.dump(dic1,sort_keys=True,indent =4,separators=(',', ': '),ensure_ascii=True )
print (json_dic)

打印输出如下:

1
2
3
4
{
"name": "Paris",
"population": 2243
}

dumps

dumps 将基本数据类型输出到一个文件中。

dumps的函数声明

1
2
3
def dumps(obj, fp, skipkeys=False, ensure_ascii=True, check_circular=True,
allow_nan=True, cls=None, indent=None, separators=None,
default=None, sort_keys=False, **kw)

例子2

1
2
3
4
fp = open('a.json', 'w')

dic1 = {'name': "Paris", 'population': 2243}
json_dic2 = json.dump(dic1,fp,sort_keys=True,indent =4,separators=(',', ': '),ensure_ascii=True )

a.json 文件内容如下:

1
2
3
4
{
"name": "Paris",
"population": 2243
}

解码

json的解码主要有 load 和 loads 两个函数来完成

load

load 函数声明

1
2
def load(s, encoding=None, cls=None, object_hook=None, parse_float=None,
parse_int=None, parse_constant=None, object_pairs_hook=None, **kw)

例子3

1
2
3
dic1 = """{"name": "Paris", "population": 2243}"""
info = json.load(dic1)
print(info)

输出为:

1
2
3
4
{
'name': 'Paris',
'population': 2243
}

loads

loads 从一个文件中读入JSON字符串并将字符串解码为基本数据类型。

1
2
3
4
fp = open('a.json', 'r',encoding='utf-8')

info = json.load(fp)
print(info)

输出为:

1
{'name': 'Paris', 'population': 2243}

格式化主要是 dumps 的时候的参数配置。

昨夜无眠,终于搞定了。还是要花时间去搞,没有什么事情是白白来的。

夏、商、周

中央

三司,大司徒,大司马,大司空

地方

郡县

春秋、战国

相(文)

将(武)

令尹

上柱国

秦汉

中枢

丞相府(相国,宰相)

禀承皇帝意旨佐理国政

太尉府

掌全国军事

御史大夫

皇帝的秘书长兼管监察

五代十国

隋唐

中书

枢密院

枢密使、副使

明清

民国

民国年间的东西已经不清楚了