
网络通信密码学IoT协议【免费下载链接】ReticulumThe cryptography-based networking stack for building unstoppable networks with LoRa, Packet Radio, WiFi and everything in between.项目地址https://gitcode.com/gh_mirrors/re/Reticulum点击查看免费下载本指南以 docs/markdown/examples.md及其 RST 源文件为骨架系统剖析 Reticulum 源码分发中自带的全部 12 个官方示例Minimal、Announce、Broadcast、Echo、Link、Identify、Requests Responses、Channel、Buffer、Filetransfer 以及 Custom Interfaces。每个示例都附有完整可运行代码并在对应小节补充了 RNS 核心模块Destination.py、Link.py、Transport.py、Channel.py、Buffer.py、Resource.py的源码级原理说明。读完本文你将掌握 Reticulum 应用开发的全部核心模式初始化协议栈、创建并通告 Destination、收发明文/加密数据包、建立加密 Link、链路双方身份认证、请求-响应 RPC、结构化消息与二进制流传输、大文件资源传输以及编写可被 Reticulum 运行时动态加载的自定义接口。示例总览与运行前置条件Reticulum 的源码分发中包含了数量众多的官方示例程序均位于 Examples 目录它们既可以直接运行演示功能更是学习用 Reticulum 编写自己程序的最佳教材。下表汇总了各示例所覆盖的 API 领域与对应源码文件示例核心主题涉及 API 模块源码文件Minimal最小化初始化与 IN 单播目的地Reticulum、Identity、DestinationExamples/Minimal.pyAnnounce目的地通告与通告回调Destination、Transport、AnnounceHandlerExamples/Announce.pyBroadcast明文广播Destination(PLAIN)、PacketExamples/Broadcast.pyEcho基于 Packet 的客户端/服务器回显Destination、Packet、PacketReceipt、Identity.recallExamples/Echo.pyLink加密链路数据交换Link、Transport.has_pathExamples/Link.pyIdentify链路发起方身份认证Link.identify、set_remote_identified_callbackExamples/Identify.pyRequest请求与响应RPC 风格Destination.register_request_handler、Link.requestExamples/Request.pyChannel结构化消息多路复用Channel、MessageBase、umsgpackExamples/Channel.pyBuffer链路二进制流读写Buffer.create_bidirectional_bufferExamples/Buffer.pyFiletransfer基于 Resource 的文件服务器Resource、Link 资源策略、umsgpackExamples/Filetransfer.pyCustom Interfaces自定义网络接口Interface 基类、HDLC 帧封装Examples/ExampleInterface.py所有示例都可以用python3 Examples/Name.py直接运行。绝大多数示例支持--config参数用于指定一个替代的 Reticulum 配置目录若不指定Reticulum 会在系统默认位置Linux 上为~/.reticulum/初始化配置。首次运行时会自动生成config配置文件并在无网络接口时自动启动一个本地共享实例shared instance使多个本地程序可以直接互相通信。示例的公共模式包括每个程序都定义了一个APP_NAME example_utilities命名空间所有目的地都建立在这个应用命名空间之下program_setup(configpath)完成协议栈初始化、Identity 创建、Destination 创建与回调注册主循环通常等待用户按回车手动触发一次destination.announce()以此在网络上通告自己的存在命令行入口统一用argparse解析参数并用KeyboardInterrupt捕获 Ctrl-C 实现优雅退出。Minimal五步接入 Reticulum 网络Minimal 示例演示了接入 Reticulum 网络所需的最精简代码约五行核心代码即可完成协议栈初始化并具备收发流量的能力。完整代码见 Examples/Minimal.py。APP_NAME example_utilities def program_setup(configpath): # 1. 初始化 Reticulum 协议栈 reticulum RNS.Reticulum(configpath) # 2. 随机生成一个新的身份 identity RNS.Identity() # 3. 基于该身份创建一个 IN 方向的单播目的地 destination RNS.Destination( identity, RNS.Destination.IN, RNS.Destination.SINGLE, APP_NAME, minimalsample ) # 4. 配置目的地自动证明所有收到的数据包 destination.set_proof_strategy(RNS.Destination.PROVE_ALL) # 5. 进入通告循环 announceLoop(destination)四个关键概念需要理解RNS.Reticulum(configpath)协议栈的唯一入口。它会读取配置目录下的配置文件、初始化 Transport 层并如有必要生成默认配置。其构造函数在 Reticulum.py 中定义还支持loglevel、logdest、verbosity等参数。RNS.Identity()随机生成的公私钥对。它是 Reticulum 中所有身份与加密的基础派生自 Ed25519 与 X25519 等密码学原语见 RNS/Cryptography。RNS.Destination(identity, direction, type, app_name, *aspects)目的地的构造参数语义由 Destination.py 中的构造函数实现direction取值RNS.Destination.IN收包或RNS.Destination.OUT发包IN 方向目的地持有完整公私钥OUT 方向只需持有对方的公钥type取值SINGLE单播加密、GROUP组播或PLAIN明文广播目的地的可寻址哈希由Destination.hash()静态方法计算先对app_name与各 aspect 展开的全名做哈希再与身份哈希拼接后截断最终得到RNS.Reticulum.TRUNCATED_HASHLENGTH//8字节的地址。set_proof_strategy目的地的证明策略可取PROVE_NONE、PROVE_ALL或PROVE_APP。设为PROVE_ALL后Reticulum 会对每个收到的数据包自动生成并回传一个 proof收包证明让发送方能够确认消息已被正确接收。若设为PROVE_APP则是否回执由set_proof_requested_callback注册的回调按应用逻辑决定。通告循环中用户每按一次回车就调用一次destination.announce()将通告数据包广播到所有相关接口上。从 Destination.py 的announce()实现可以看到通告包内含目的地哈希、公钥、名称哈希、随机数与身份签名并可选携带app_data整个结构通过RNS.Packet(..., RNS.Packet.ANNOUNCE, ...)发出。网络中任何节点收到该通告后就会自动创建到该目的地的路径path从而实现从网络任意位置都能路由到它的效果。Announce目的地通告与通告处理器Announce 示例在 Minimal 之上引入了两个新能力向通告中携带应用数据app_data以及注册通告处理器来接收与自己相关的通告通知。完整代码见 Examples/Announce.py。示例在example_utilities.announcesample应用空间下创建了两个 IN 单播目的地并分别绑定 fruits 与 noble_gases 两个 aspectdestination_1 RNS.Destination(identity, RNS.Destination.IN, RNS.Destination.SINGLE, APP_NAME, announcesample, fruits) destination_2 RNS.Destination(identity, RNS.Destination.IN, RNS.Destination.SINGLE, APP_NAME, announcesample, noble_gases)通告时随机挑选列表中的字符串编码为 UTF-8 字节作为 app_datadestination_1.announce(app_datafruit.encode(utf-8)) destination_2.announce(app_datanoble_gas.encode(utf-8))通告处理器的核心是aspect_filter机制——处理器只接收 aspect 完全匹配的通告且过滤器必须精确指定不支持通配符announce_handler ExampleAnnounceHandler( aspect_filterexample_utilities.announcesample.fruits ) RNS.Transport.register_announce_handler(announce_handler)处理器类需实现received_announce方法签名与 Transport.py 中register_announce_handler的文档约束一致处理器对象必须具备aspect_filter属性与可调用的received_announce(destination_hash, announced_identity, app_data)方法可选扩展为received_announce(destination_hash, announced_identity, app_data, announce_packet_hash)或额外携带is_path_response的版本若设置receive_path_responses True还会额外接收路径响应通告class ExampleAnnounceHandler: def __init__(self, aspect_filterNone): self.aspect_filter aspect_filter def received_announce(self, destination_hash, announced_identity, app_data): RNS.log(Received an announce from RNS.prettyhexrep(destination_hash)) if app_data: RNS.log(The announce contained the following app data: app_data.decode(utf-8))把 aspect_filter 改为example_utilities.announcesample.noble_gases处理器就会转而只接收惰性气体目的地的通告。这个机制是 NomadNet、Sideband 等上层应用发现服务端目的地的标准手段。Broadcast明文广播通道Broadcast 示例演示如何向网络上所有正在监听的节点广播明文信息代码见 Examples/Broadcast.py。关键差异在于目的地的 type 参数if channel None: channel public_information broadcast_destination RNS.Destination( None, # PLAIN 目的地不能持有身份 RNS.Destination.IN, RNS.Destination.PLAIN, # 明文广播类型 APP_NAME, broadcast, channel ) broadcast_destination.set_packet_callback(packet_callback)要点解析PLAIN 目的地是不加密的端点任何节点都能监听并向其发送信息。源码中 Destination.py 规定PLAIN 类型不能持有 Identity且在identity None and direction IN且类型非 PLAIN 时会自动生成身份——因此广播目的地显式传入None即可。channel 参数被加入目的地名称空间用于区分不同的广播通道示例默认通道名为public_information通过--channel命令行参数可指定任意自定义通道不同通道互不干扰。通过set_packet_callback(packet_callback)注册收包回调回调签名固定为(data, packet)数据是已解包的原始字节。发送方构造RNS.Packet(destination, data)后调用packet.send()即可将 UTF-8 编码的用户输入广播出去。注意此处未请求证明proof因此广播是尽力而为的。命令行同时支持--config与--channel两个参数python3 Examples/Broadcast.py --channel my_channelEcho基于 Packet 的客户端/服务器回显Echo 示例演示了两个目的地之间通过 Packet 接口进行的完整通信闭环客户端发送回显请求服务器自动回传收包证明并附带物理层接收质量参数。完整代码见 Examples/Echo.py其命令行入口支持三种参数python3 Examples/Echo.py -s # 以服务器模式运行 python3 Examples/Echo.py destination_hex # 以客户端模式运行 python3 Examples/Echo.py -t 5 destination_hex # 客户端并设置 5 秒回复超时服务器端服务器创建 IN 单播目的地example_utilities.echo.request配置PROVE_ALL证明策略与收包回调echo_destination RNS.Destination( server_identity, RNS.Destination.IN, RNS.Destination.SINGLE, APP_NAME, echo, request ) echo_destination.set_proof_strategy(RNS.Destination.PROVE_ALL) echo_destination.set_packet_callback(server_callback)server_callback中演示了物理层接收质量的获取方式当协议栈连接了共享实例shared instance时通过reticulum.get_packet_rssi(packet.packet_hash)与reticulum.get_packet_snr(packet.packet_hash)查询否则直接读取packet.rssi与packet.snr属性并分别以 dBm/dB 为单位打印。客户端客户端流程体现了先寻路、再取身份、后发包的标准三步曲校验并解析目的地哈希目的地的十六进制哈希长度必须等于(RNS.Reticulum.TRUNCATED_HASHLENGTH//8)*2否则报错退出查询路径RNS.Transport.has_path(destination_hash)判断是否已知到服务器的路由未知时调用RNS.Transport.request_path(destination_hash)请求路径并提示用户等待通告到达后重试召回服务器身份并构造 OUT 目的地server_identity RNS.Identity.recall(destination_hash) request_destination RNS.Destination( server_identity, RNS.Destination.OUT, RNS.Destination.SINGLE, APP_NAME, echo, request )Identity.recall()是 Identity.py 中的静态方法Reticulum 会把从通告中学到的目的地公钥持久化保存recall按目的地哈希取回对应的Identity实例供 OUT 目的地使用。发送回显请求echo_request RNS.Packet(request_destination, RNS.Identity.get_random_hash()) packet_receipt echo_request.send() if timeout ! None: packet_receipt.set_timeout(timeout) packet_receipt.set_timeout_callback(packet_timed_out) packet_receipt.set_delivery_callback(packet_delivered)send()返回一个PacketReceipt若发送失败返回 False。set_timeout与set_timeout_callback配置超时行为set_delivery_callback(packet_delivered)注册投递回调——当收到来自目的地的 proof 时自动触发。packet_delivered中通过receipt.status RNS.PacketReceipt.DELIVERED判断成功并用receipt.get_rtt()计算往返时延大于 1 秒显示为秒否则显示为毫秒同时同样可读取 proof 包的 RSSI/SNR。packet_timed_out则在receipt.status RNS.PacketReceipt.FAILED时打印超时信息。Link建立加密链路并双向传输数据Link 示例展示如何与远端目的地建立加密链路Link并在链路上双向传递数据。完整代码见 Examples/Link.py。服务器端服务器创建可接受链路请求的单播目的地并通过set_link_established_callback注册新客户端连入回调server_destination RNS.Destination( server_identity, RNS.Destination.IN, RNS.Destination.SINGLE, APP_NAME, linkexample ) server_destination.set_link_established_callback(client_connected)client_connected(link)收到 Link 实例后为其注册链路关闭回调与收包回调并保存到全局变量以便后续回复def client_connected(link): global latest_client_link RNS.log(Client connected) link.set_link_closed_callback(client_disconnected) link.set_packet_callback(server_packet_received) latest_client_link link收到链路数据后服务器直接把最新客户端连接作为回复的目的地reply_data (I received \text\ over the link).encode(utf-8) RNS.Packet(latest_client_link, reply_data).send()客户端客户端流程校验哈希 →Transport.has_path检查路径未知则Transport.request_path并轮询等待 →Identity.recall取服务器公钥 → 构造 OUT 单播目的地 → 创建链路server_destination RNS.Destination( server_identity, RNS.Destination.OUT, RNS.Destination.SINGLE, APP_NAME, linkexample ) link RNS.Link(server_destination) link.set_packet_callback(client_packet_received) link.set_link_established_callback(link_established) link.set_link_closed_callback(link_closed)链路建立后client_loop等待server_link就绪然后逐行读取用户输入并通过RNS.Packet(server_link, data).send()发送。发送前必须检查数据长度是否超过RNS.Link.MDUMaximum Data Unit链路最大数据单元超过 MDU 的数据包会被拒绝并打印RNS.LOG_ERROR级别的错误日志。MDU 的计算公式定义在 Link.pyMDU math.floor((RNS.Reticulum.MTU-RNS.Reticulum.IFAC_MIN_SIZE-RNS.Reticulum.HEADER_MINSIZE-RNS.Identity.TOKEN_OVERHEAD)/RNS.Identity.AES128_BLOCKSIZE)*RNS.Identity.AES128_BLOCKSIZE - 1即从协议栈 MTU 中扣除接口最小开销、最小报文头与令牌开销再按 AES-128 块大小向下取整并减去 1保证链路载荷必然能容纳加密块。客户端发送quit、q或exit时调用server_link.teardown()主动拆除链路链路关闭回调则根据link.teardown_reason区分关闭原因RNS.Link.TIMEOUT链路超时、RNS.Link.DESTINATION_CLOSED对端关闭或其他情况打印对应提示后退出程序。Identification链路发起方身份认证Identify 示例在 Link 之上增加了链路发起方的身份认证能力代码见 Examples/Identify.py。其价值在于链路建立本身并不暴露双方身份通过identify可以让对端知道谁在与我通信且该身份只在加密链路内传输对网络中的第三方保持匿名。客户端在链路建立回调中调用link.identify(client_identity)def link_established(link): global server_link, client_identity server_link link RNS.log(Link established with server, identifying to remote peer...) link.identify(client_identity)从 Link.py 的实现可以看到identify()将链路 ID 与身份公钥拼接后签名以LINKIDENTIFY上下文的 DATA 数据包经加密链路发送该方法仅当self.initiator and self.status Link.ACTIVE发起方且链路已激活时有效。服务器端注册远端身份识别回调link.set_remote_identified_callback(remote_identified) def remote_identified(link, identity): RNS.log(Remote identified as: str(identity))在服务器收包回调中通过packet.link.get_remote_identity()获取发起方身份未识别时返回 None显示为unidentified peer从而在日志中区分消息来源remote_peer unidentified peer if packet.link.get_remote_identity() ! None: remote_peer str(packet.link.get_remote_identity())这套机制为基于 Reticulum 的应用提供了可选的认证层常用于构建授权访问类的服务。Requests Responses请求-响应 RPCRequest 示例演示了在链路上执行请求-响应RPC 风格调用客户端向服务器发起命名请求服务器用响应生成器response generator返回结果。完整代码见 Examples/Request.py。服务器端注册请求处理器server_destination.register_request_handler( /random/text, response_generator random_text_generator, allow RNS.Destination.ALLOW_ALL )register_request_handler的参数语义定义于 Destination.pypath请求路径字符串示例中为/random/textresponse_generator响应生成函数签名固定为(path, data, request_id, link_id, remote_identity, requested_at)返回值将作为响应发送给请求方返回None则不发送响应allow请求策略可取ALLOW_NONE、ALLOW_ALL或ALLOW_LIST后者仅对allowed_list中列出的身份哈希响应另有可选参数auto_compress控制响应自动压缩行为。示例的响应生成器从预置文本列表中随机选择一句返回def random_text_generator(path, data, request_id, link_id, remote_identity, requested_at): RNS.log(Generating response to request RNS.prettyhexrep(request_id) on link RNS.prettyhexrep(link_id)) texts [They looked up, On each full moon, Becky was upset, Ill stay away from it, The pet shop stocks everything] return texts[random.randint(0, len(texts)-1)]客户端发起请求客户端在链路建立后每按一次回车就发起一次请求并注册成功/失败回调server_link.request( /random/text, data None, response_callback got_response, failed_callback request_failed )Link.request()定义于 Link.py请求体为[时间戳, 路径哈希, 数据]的 MessagePack 编码使用RNS.vendor.umsgpack若请求体不超过链路 MDU 则作为普通 REQUEST 上下文数据包发送并返回RequestReceipt否则自动升级为 Resource 传输。超时未指定时由链路 RTT 与RNS.Resource.RESPONSE_MAX_GRACE_TIME推算。回调从request_receipt中读取结果def got_response(request_receipt): request_id request_receipt.request_id response request_receipt.response RNS.log(Got response for request RNS.prettyhexrep(request_id): str(response))请求-响应机制是 rnsh、rncp 等 Reticulum 实用工具见 RNS/Utilities内部的核心通信原语。Channel在链路上多路复用结构化消息Channel 示例展示如何通过Channel在Link的对等节点之间发送结构化数据对象。Channel 在单条链路上提供消息多路复用、序列化/反序列化与投递确认是 Reticulum 面向应用的高级传输抽象。完整代码见 Examples/Channel.py底层实现在 Channel.py。定义消息类型所有通过 Channel 传输的数据对象都必须继承RNS.MessageBase并实现三个约定class StringMessage(RNS.MessageBase): # 1. MSGTYPE 必须是唯一的 2 字节整数 # 0xf000 的值保留给系统使用 MSGTYPE 0x0101 # 2. 构造函数必须允许无参调用参数需带默认值 # 以便 Channel 反序列化时创建空对象再填充 def __init__(self, dataNone): self.data data self.timestamp datetime.now() # 3. 实现 pack/unpack 完成字节流编码与解码 def pack(self) - bytes: return umsgpack.packb((self.data, self.timestamp)) def unpack(self, raw): self.data, self.timestamp umsgpack.unpackb(raw)注意事项均已在示例注释中说明MSGTYPE是 Channel 在收到消息时查找对应构造函数的键必须在注册到同一 Channel 的所有消息类型中唯一示例使用 Reticulum 内置的RNS.vendor.umsgpack打包如需对字节结构有更精细的控制也可改用 Python 标准库struct打包后的消息必须能完整放进单个数据包可用channel.MDUChannel 最大数据单元略小于 Link MDU因为要额外编码消息头查询可用的载荷上限。双端注册与收发链路两端必须注册相同的消息类型才能互通。服务器端在客户端连入回调中配置def client_connected(link): global latest_client_link latest_client_link link RNS.log(Client connected) link.set_link_closed_callback(client_disconnected) channel link.get_channel() channel.register_message_type(StringMessage) channel.add_message_handler(server_message_received)link.get_channel()返回该链路专属的 Channel 实例每条链路的 Channel 相互独立。客户端在链路建立回调中做同样的注册然后即可通过channel.send(message)发送消息message StringMessage(text) packed_size len(message.pack()) channel server_link.get_channel() if channel.is_ready_to_send(): if packed_size channel.mdu: channel.send(message) else: RNS.log(Cannot send this packet, the data size of str(packed_size) bytes exceeds the link packet MDU of str(channel.MDU) bytes, RNS.LOG_ERROR) else: RNS.log(Channel is not ready to send, please wait for pending messages to complete., RNS.LOG_ERROR)发送前先用is_ready_to_send()检查发送窗口并用channel.mdu校验消息大小。消息处理器按注册顺序被调用只要某个处理器返回True即视为已处理后续处理器被跳过def server_message_received(message): if isinstance(message, StringMessage): RNS.log(Received data on the link: message.data (message created at str(message.timestamp) )) reply_message StringMessage(I received \message.data\ over the link) latest_client_link.get_channel().send(reply_message) return TrueBuffer链路上的二进制流读写Buffer 示例演示如何通过带缓冲的读写器在链路对等节点之间发送二进制数据代码见 Examples/Buffer.py。它把 Channel 进一步封装成类似文件对象的流式接口底层实现位于 Buffer.py。双端在链路建立/客户端连接时创建双向缓冲channel link.get_channel() buffer RNS.Buffer.create_bidirectional_buffer(0, 0, channel, buffer_ready_callback)create_bidirectional_buffer(receive_stream_id, send_stream_id, channel, ready_callback)返回一个BufferedRWPair。示例注释解释了两个关键点stream_id类似文件描述符但它对接收方唯一示例中读写都使用stream_id 0实际上存在两条方向相反、彼此独立的单向流服务器若收到新的客户端连接需要先latest_buffer.close()关闭旧连接的缓冲。数据就绪回调收到可读字节数后读取并解码def server_buffer_ready(ready_bytes: int): global latest_buffer data latest_buffer.read(ready_bytes) data data.decode(utf-8) RNS.log(Received data over the buffer: data) reply_message (I received \data\ over the buffer).encode(utf-8) latest_buffer.write(reply_message) latest_buffer.flush()客户端在交互循环中写入数据后必须显式调用buffer.flush()以强制将数据发送出去text text.encode(utf-8) buffer.write(text) buffer.flush()Buffer 在 Buffer.py 中还提供了create_reader单向读可指定就绪回调与create_writer单向写返回分别实现readinto/writable/readable与write等类文件接口的对象支持with上下文管理。这使得任意大小的字节流都能以流式方式在链路上传输而无需关心底层分片。Filetransfer基于 Resource 的文件服务器Filetransfer 示例实现了一个完整的文件服务器客户端连接后可列出服务器目录中的文件并下载任意大小的文件传输基于 Resource 接口高效完成。完整代码见 Examples/Filetransfer.py。命令行入口python3 Examples/Filetransfer.py -s ./files # 以服务器模式托管 ./files 目录 python3 Examples/Filetransfer.py destination_hex # 以客户端模式连接服务器 python3 Examples/Filetransfer.py --config /path/to/config destination_hex服务器端实现服务器创建example_utilities.filetransfer.server目的地并注册链路建立回调客户端连入后服务器用umsgpack.packb(list_files())将文件列表打包成单个数据包发送若超过RNS.Link.MDU则报错并提示应自行拆分客户端已具备合并多条列表包的能力data umsgpack.packb(list_files()) if len(data) RNS.Link.MDU: list_packet RNS.Packet(link, data) list_receipt list_packet.send() list_receipt.set_timeout(APP_TIMEOUT) # 默认 45 秒 list_receipt.set_delivery_callback(list_delivered) list_receipt.set_timeout_callback(list_timeout) else: RNS.log(Too many files in served directory!, RNS.LOG_ERROR)之后通过link.set_packet_callback(client_request)等待客户端发来文件名。收到合法文件名后把打开的文件句柄交给RNS.Resource发起资源传输file open(os.path.join(serve_path, filename), rb) file_resource RNS.Resource(file, packet.link, callbackresource_sending_concluded) file_resource.filename filenameresource_sending_concluded依据resource.status是否为RNS.Resource.COMPLETE判定传输是否成功。客户端实现客户端为链路启用资源自动接收策略与进度回调server_destination.set_proof_strategy(RNS.Destination.PROVE_ALL) link.set_packet_callback(filelist_received) link.set_resource_strategy(RNS.Link.ACCEPT_ALL) link.set_resource_started_callback(download_began) link.set_resource_concluded_callback(download_concluded)set_resource_strategy的参数由 Link.py 定义ACCEPT_NONE不自动接受、ACCEPT_APP由set_resource_callback决定或ACCEPT_ALL自动接受全部资源。下载开始时download_began记录时间与传输尺寸download_concluded在resource.status RNS.Resource.COMPLETE时把resource.data.read()写入磁盘若文件已存在则自动追加.1、.2序号避免覆盖并展示耗时、文件大小、有效速率与传输速率等统计信息。示例头部注释给出了一个重要工程建议使用 Resource 传输大文件并不理想——压缩、加密与哈希图hashmap切分在慢 CPU 上可能耗时过长导致客户端在资源准备完成前超时需要传输大文件时应改用 Bundle 类自动将数据切成适合封装为 Resource 的分块。Custom Interfaces编写可被运行时加载的自定义接口ExampleInterface 演示如何为 Reticulum 创建自定义网络接口。自定义接口与内置接口完全同权支持全部接口模式interface modes与通用配置项common configuration options且数量不限。完整代码见 Examples/ExampleInterface.py。加载方式与配置将自定义接口文件放入~/.reticulum/interfaces/目录然后在 Reticulum 配置文件中添加一个接口条目示例文件头部的注释即给出了可复制的配置模板[[Example Custom Interface]] type ExampleInterface enabled no mode gateway port /dev/ttyUSB0 speed 115200 databits 8 parity none stopbits 1实现要点自定义接口必须继承RNS.Interface基类构造函数签名固定为__init__(self, owner, configuration)owner 为 Transport 实例configuration 为配置字典并在文件末尾声明interface_class ExampleInterface作为 Reticulum 运行时加载的目标类。示例中的核心实现如下class ExampleInterface(Interface): DEFAULT_IFAC_SIZE 8 # 所有接口类都必须提供默认 IFAC 大小字节 def __init__(self, owner, configuration): # 1. 检查可选依赖示例接口依赖 pyserial import importlib if importlib.util.find_spec(serial) ! None: import serial else: RNS.log(Using this interface requires a serial communication module to be installed., RNS.LOG_CRITICAL) RNS.log(You can install one with the command: python3 -m pip install pyserial, RNS.LOG_CRITICAL) RNS.panic() # 2. 初始化父类并用基类工具方法规范化配置 super().__init__() ifconf Interface.get_config_obj(configuration) # 3. 读取配置并提供默认值 name ifconf[name] port ifconf[port] if port in ifconf else None speed int(ifconf[speed]) if speed in ifconf else 9600 databits int(ifconf[databits]) if databits in ifconf else 8 parity ifconf[parity] if parity in ifconf else N stopbits int(ifconf[stopbits]) if stopbits in ifconf else 1 if port None: raise ValueError(fNo port specified for {self}) # 4. 必须向 Transport 提供硬件 MTU # 底层介质在不分段情况下能承载的最大数据包载荷字节数 self.HW_MTU 564 self.online False self.bitrate speed ...接口需要实现的关键回调方法包括process_incoming(data)从底层介质收到完整数据包时调用更新rxb计数后交给self.owner.inbound(data, self)交给 Transport 处理process_outgoing(data)Transport 需要发送数据包时调用示例先用简化 HDLC 帧封装FLAG 0x7E、ESC 0x7D、ESC_MASK 0x20再写入串口并校验实际写入字节数read_loop()后台线程持续从串口读取字节按 HDLC 标志位进行成帧与转义还原组装出完整数据包后调用process_incoming超时清空半帧reconnect_port()串口断开后每 5 秒尝试重连should_ingress_limit()返回False表示该接口不做入口限流__str__()返回ExampleInterface[name]形式的可读标识。示例还演示了错误处理模式读取线程异常时置self.online False并关闭串口若RNS.Reticulum.panic_on_interface_error为真则调用RNS.panic()否则记录日志并周期性重连。测试佐证与进一步学习Reticulum 仓库的测试套件tests 目录为上述机制提供了可运行验证例如 tests/egress.py 通过构造TransmitBuffer与伪套接字验证了背压限流与超大帧拒绝逻辑展示了接口层收发路径的行为约束tests/hdlc.py 覆盖 HDLC 成帧/解帧可用于理解 ExampleInterface 中 read_loop 的状态机。各示例对应的源文件与文档源文件保持同步Examples 目录与 docs/source/examples.rst 的literalinclude一一对应。进一步阅读建议协议栈初始化与配置目录结构Reticulum.py目的地类型、证明策略与请求处理器Destination.py链路生命周期、请求 API 与资源策略Link.py通告处理器注册与路径发现Transport.py结构化消息 Channel 与二进制流 BufferChannel.py、Buffer.py大文件资源传输Resource.py自定义接口基类与通用配置项Interface.py 与 docs/markdown/interfaces.md。从一行RNS.Reticulum()开始到自定义接口接入底层介质这 12 个官方示例覆盖了 Reticulum 应用开发的全栈路径。建议按 Minimal → Announce → Echo → Link → Request → Channel → Buffer → Filetransfer 的顺序动手运行再阅读对应源码模块即可完整掌握以密码学为基础的 Reticulum 网络编程模型。赞分享网络通信密码学IoT协议【免费下载链接】ReticulumThe cryptography-based networking stack for building unstoppable networks with LoRa, Packet Radio, WiFi and everything in between.项目地址https://gitcode.com/gh_mirrors/re/Reticulum点击查看免费下载相关推荐Reticulum 官方代码示例全解从最小接入、加密链路到自定义接口的实战指南Reticulum 官方代码示例全解从最小接入、加密链路到自定义接口的实战指南 本篇技术指南以 Reticulum 官方文档《Code Examples》源网络通信密码学IoT协议DeepChem 数据加载实战用 pandas 与 SDFLoader 把 CSV/SDF 文件变成分子数据集DeepChem 数据加载实战用 pandas 与 SDFLoader 把 CSV/SDF 文件变成分子数据集 本指南围绕 examples/data_loa网络通信密码学IoT协议推理引擎边界设计DwarfStar 如何用窄公共 API 隔离 CLI 与张量内部推理引擎边界设计DwarfStar 如何用窄公共 API 隔离 CLI 与张量内部 DwarfStar 是一个支持 Metal、CUDA 和 ROCm 的本地网络通信密码学IoT协议上一篇人工智能安全响应Awesome Incident Response机器学习工具集成方案下一篇MagicDance革命性AI舞蹈生成10分钟快速入门指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考