一直想让单片机(尤其是51)联网,感觉这样很好玩。但是没有非常轻量的ip实现,而且本人不太想让单片机用ip网络(占地址)。于是设计了非常轻量的网络协议栈,称为zxdnet(简称znet)。他可以工作对mtu的最小要求是48字节,所以可以在很多链路上,例如串口和红外。他很适合爱好者用来玩,也可以用于学习网络原理。znet适用于构建完全私有的组织内网络而不是公共网络。
报文中所有字段都是大端序的。
znet和ip一样是采用分层架构的分组交换网络,数据包可以经过多个路由器转发后到达目的地。
首先介绍下znet的网络层协议zp的报头:
介绍下各字段:
BF(2bit):基本标志。前1bit表示目标地址类型,如果是0目标地址为普通地址,如果是1目标地址为组播地址(目前还没设计组播)。后1bit表示无错误标志,如果此位为1,在发生错误的时候就不会通过zcp协议回报错误(类似ip中的icmp错误回报)
Proto(4bit):上层协议号
0: ZARP (ZXDNET 地址解析协议)
1: ZCP (ZXDNET 控制协议)
2: TUDP (简单用户数据报协议)
3: UDP (用户数据报协议)
4: TCP (传输控制协议)
5: IPoZP (IP over ZP)
6: RAW
7-15: 用户自定义
Time To Live(8bit):TTL
这个字段定义了数据报允许的最大跳数。发送方初始化这个值,每个路由节点在处理时将其减一。如果TTL在数据报到达目的地之前变为零,数据报会立即被丢弃。这个机制防止了无限路由循环。
Extra Flag(16bit):额外标志。用户自定义,一般用于qos。
Total Length (16bit):报文总长度(字节),包括网络层头(16字节)及其数据。
Header Checksum(16bit):首部校验和。
仅对头部字段计算校验和。由于某些头部字段(例如生存时间)在传输过程中可能会改变,因此每个处理头部的节点都必须验证和重新计算这个校验和。
校验和字段是头部中所有16位字的反码和的16位反码。在计算过程中,校验和字段本身被视为零。如果计算出的校验和为零,则以全1的形式传输。如果校验和字段本身为0,就跳过校验,这适用于可靠链路。
Source Address和Destination Address:源地址和目标地址。
地址分配:
Zxdnet使用32位地址空间,采用CIDR,分类如下:
未指定/本地广播地址(0.0.0.0/32):
位模式:00000000 00000000 00000000 00000000。
作为源:未初始化设备(例如,启动时的0.0.0.0)。
作为目的地:有限广播(在子网之外不可路由)。
回环地址(0.0.0.128/25):
位模式:00000000 00000000 00000000 1XXXXXXX。
仅限于内部主机通信。
NAT扩展地址(0.0.0.64/26):
位模式:00000000 00000000 00000000 01XXXXXX。
仅限于本地地址扩展。
NAT处理:典型的NAT中间盒有两个接口,一个连接到包含最多63个NAT设备的局域网(接口地址为0.0.0.64/26),另一个连接到全球网络(具有全局单播地址)。对于使用端口号的传输层协议,NAT设备将全局单播地址的端口号划分为几个段,每个段包含相同数量的端口。这些端口然后映射到每个设备的前几个端口号(从0开始)。中间盒本身将被分配第一个端口段。例如,对于一个总共有256个端口的传输层协议,NAT设备将这些端口划分为64个段,每个段包含4个端口。端口0-3由中间盒使用,端口4-7映射到第一个NAT设备的端口0-3,依此类推,端口252-255映射到第63个NAT设备的端口0-3。对于ZCP Echo和ZCP错误报告,中间盒充当代理。ZARP和IPoZP不支持NAT穿越。NAT嵌套不被支持。
保留地址(0.0.0.1-0.0.0.63):
位模式:00000000 00000000 00000000 00XXXXXX(XXXXXX!=000000)。
这些地址不得分配给任何设备或用于数据报头。
单播地址(所有非保留地址):
分配给设备,全局可路由。
znet地址空间中只有256个为特殊用途,其他全部可以分配给设备。znet没有所谓“网络地址“,表示一个网络可以用第一个设备地址+子网前缀长度。znet也没有所谓”局域网广播地址“,只有一个不可跨网关的有限广播地址0.0.0.0。这样的设计十分简化,可以高效实现,节省地址。
zp协议不支持网络层分片,因为违反了网络层无连接原则,并且一些运输层不需要,占用了头部空间。
下面介绍一些运输层协议(上面提到的)。
首先是zarp协议。他设计的很简洁。如果链路层目标地址是广播地址就是请求,是设备地址就是响应。
zcp协议用于控制和诊断网络本身。校验和算法与zp头的一致,但是涵盖zcp头和他的数据。zcp报文最大48字节(包括zp头)。zcp目前有2个作用:错误回报和回显。首先说下错误回报报文。
以下是errcode定义:
0 = 网络不可达。
1 = 主机不可达。
2 = 协议不可达。
3 = 端口不可达。
4 = 超出MTU。
5 = 生存时间在传输中超出。
6 = 数据丢失。
7 = 数据损坏。
8 = 链路拥塞。
9 = 显式拥塞通告。
10 = 不支持组播。
注意,如果是超出MTU,原始zp头里的校验和字段会被替换为mtu。
然后介绍下回显报文。
code=0就是回显请求,code=1就是回显响应。对方收到后改变code,重新计算校验和,然后发回报文, Identifier ,Sequence Number和Data不能改变。
data是用户数据,最大22字节。
znet支持跨nat ping。Source Host和 Destination Host就是为了跨nat ping。在正常情况下,当设备发送 echo 请求时,这两个字段都设置为 0。如果 NAT 设备向另一台设备发送 Echo 请求,则中间框会将 Source Host 字段设置为其标识符(与地址的低 6 位匹配),以便将 Echo 回复路由回 NAT 设备。如果设备想要向 NAT 设备发送 echo 请求,则必须将 Destination Host 字段设置为 NAT 设备的标识符,并将 echo 请求发送到中间盒。在将请求转发到目标 NAT 设备之前,中间框会自动将 Destination Host 字段设置为零。当目标 NAT 设备返回回声回复时,中间框将使用 NAT 设备的标识符重写该字段,并将响应转发回发起回声请求的设备。
最后介绍tudp协议。
这个报文头简单,无需过多讲解。校验和需要涵盖tudp头部和他的数据。tudp最大允许28字节的数据,从而可以在单片机上高效运行。
znet其余的设计以后补充。
znet主要用途是研究和学习,以及让单片机联网。znet目前还没有被实现,我会尽快实现他。欢迎大家一起探讨,研究,使用,提出修改意见!
本人是业余爱好者,znet可能有不完善之处,请大家尽管提出
|