分布式系统与物联网架构中的网络通信技术
1. 网络路由配置
在网络通信中,路由配置是基础。可以通过指定地址和子网掩码来创建 IP 协议中的路由,以到达子网中的所有邻居。以下是相关代码示例:
pico_ipv4_link_add(&dev, ipaddr, netmask);
添加默认路由时,将网关与 0.0.0.0 地址(表示任何主机)关联,度量值为 1。后续可以通过为其他子网定义更具体的路由来覆盖默认网关:
pico_ipv4_route_add(any, any, gw, 1, NULL);
应用程序初始化套接字并关联回调函数,以便在需要时由协议栈调用:
application_init_sockets();
通过一个简单的主循环反复调用
pico_stack_tick
函数,该函数会按轮询方式检查所有关联的网络接口,并执行所有协议模块中的待处理操作:
while (1)
pico_stack_tick();
WFI();
2. 套接字通信
2.1 lwIP 裸机套接字通信
lwIP 为裸机套接字通信提供的接口(即原始套接字 API)由自定义调用组成,每个调用在期望从协议栈收到事件时指定一个回调函数。当特定事件发生时,lwIP 会从主循环函数中调用该回调函数。
TCP 套接字在 lwIP 中的描述包含在特定于 TCP 的协议控制块结构
tcp_pcb
中。分配新的监听 TCP 套接字控制块的函数如下:
struct tcp_pcb *tcp_new(void);
裸机 lwIP TCP 服务器接受 TCP 连接时,首先调用以下函数将套接字绑定到本地地址并使其进入监听状态:
err_t tcp_bind(struct tcp_pcb *pcb, ip_addr_t *ipaddr, u16_t port);
err_t tcp_listen(struct tcp_pcb *pcb);
与使用阻塞套接字的 POSIX 应用程序不同,lwIP 裸机应用程序调用以下函数表示服务器准备好接受新连接,并在新连接建立时回调传入的
accept
函数:
void tcp_accept(struct tcp_pcb *pcb,
err_t (* accept)(void *arg, struct tcp_pcb *newpcb, err_t err)
);
接收下一个数据段时,应用程序调用以下函数:
void tcp_recv(struct tcp_pcb *pcb,
err_t (* recv)(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err)
);
2.2 picoTCP 套接字通信
picoTCP 为每个套接字对象关联一个回调函数,该回调函数是对任何与套接字相关事件做出反应的公共点。创建套接字时指定回调函数:
struct pico_socket *pico_socket_open(uint16_t net,
uint16_t proto,
void (*wakeup)(uint16_t ev, struct pico_socket *s));
在新创建的套接字上配置 TCP 套接字服务器的函数如下:
int pico_socket_bind(struct pico_socket *s,
void *local_addr,
uint16_t *port);
int pico_socket_listen(struct pico_socket *s, int backlog);
应用程序等待传入连接时无需调用
accept
,新连接建立时会生成一个事件调用
wakeup
函数,此时应用程序可以调用
pico_socket_accept
生成对应于传入连接的新套接字对象:
struct pico_socket *pico_socket_accept(
struct pico_socket *s,
void *orig,
uint16_t *local_port);
picoTCP
wakeup
回调函数的第一个参数是一个位掩码,指示套接字上发生的事件类型,具体如下:
- EV_RD:表示传入数据缓冲区中有数据可读。
- EV_CONN:表示在调用
connect
后或在监听状态下调用
accept
之前建立了新连接。
- EV_CLOSE:当连接的另一方发送 FIN TCP 段,表示其传输已完成时触发。此时套接字处于 CLOSE_WAIT 状态,应用程序在终止连接前仍可发送数据。
- EV_FIN:表示套接字已关闭,回调返回后该套接字不可再用。
- EV_ERR:表示发生错误。
3. 无连接协议
TCP 是一种广泛使用的传输协议,适用于面向连接的应用场景。而其无连接的对应协议 UDP 则主要用于解决不同范围的问题,在某些情况下可以满足小型、资源受限嵌入式系统的所有需求。
TCP 实现通常较大,在某些平台上会占用相当大的可用闪存空间。这是因为 TCP 具有复杂的内部机制,需要大量代码来管理重传、超时和确认,组织缓冲区,并为每个套接字跟踪多个状态机。
UDP 则非常简单,对从套接字接口到网络以及反之的数据进行的转换很少。通常,UDP 实现的大小要小得多,并且由于不需要可靠性保证,不需要跟踪已传输或接收数据的顺序和间隙,从而也影响了运行时的 RAM 使用。当网络特性允许时,使用 UDP 进行低流量冗余数据传输通常是一个可行的选择。
4. 网状网络和动态路由
4.1 网状网络概述
链路层协议可能能够实现 mesh-under 机制,为上层隐藏拓扑的复杂性。当链路层协议未实现此功能,或者网状解决方案需要跨不同网络接口扩展时,必须实现一种与接口无关的标准协议。每个链路连接两个直接可见的设备,这些设备会根据检测到的拓扑协调,以找到到达远程节点的最佳网络路径。路径上的中间节点会根据当前拓扑信息将流量路由到目的地。
在某些场景中,拓扑不是固定的,当路径中的节点不可用或改变位置时,拓扑会发生变化,这种非静态拓扑的网状网络称为移动自组织网络(MANETs)。为 MANETs 设计的动态路由机制必须能够对拓扑变化做出反应并相应地更新路由。
4.2 动态路由协议分类
基于动态 IP 路由的网状网络依赖不同的协议,可分为以下两类:
| 协议类型 | 特点 | 常用协议 |
| ---- | ---- | ---- |
| 主动动态路由协议 | 每个网络节点发送广播消息宣布其在网络中的存在,其他节点通过读取消息检测邻居的存在,并将邻居列表传达给邻居。网状网络随时可用,拓扑变化时需要固定的重新配置时间。 | 优化链路状态路由(OLSR)、移动自组网更好方法(B.A.T.M.A.N.)、Babel、目的序列距离向量(DSDV) |
| 被动动态路由协议 | 节点在无数据交换时可以空闲,然后通过查询每个邻居请求到目的地的路由来配置路径。消息会重复发送并增加计数器以跟踪跳数,直到到达目的地,然后根据回复定义发送方请求的路径。动态路由按需形成,通信的第一条消息可能会有额外延迟,但需要的功率较少,对拓扑变化的反应可能更快。 | 自组织按需距离向量(AODV)、动态源路由 |
picoTCP 支持一种 mesh-under 机制(在 6LoWPAN 链路层)和两种 route-over 协议(OLSR 和 AODV),为将 TCP/IP 通信集成到移动自组织网络提供了更多选择。启用 OLSR 只需编译支持 OLSR 的协议栈,OLSR 守护进程服务将自动启用并在主 TCP/IP 协议栈循环中运行,通过调用以下函数添加参与网状网络定义的设备:
pico_olsr_add(struct pico_device *dev);
启用 AODV 网络类似,使用以下函数添加接口:
pico_aodv_add(struct pico_devices *dev);
路由协议(如 OLSR)在计算网状网络中到给定目的地的最佳路径时,可以考虑除跳数之外的其他参数,例如无线链路质量信息(如信噪比或接收信号强度指示),从而基于多个参数选择路由,始终选择无线信号方面的最佳选项。
route-over 网状网络策略没有预见转发广播数据包的机制,这必须由链路层协议重复以到达网络中的所有节点。但实现此类机制容易触发乒乓效应,因此链路层实现的广播转发机制必须通过跟踪最近转发的几帧来避免重复转发同一帧。
graph LR
classDef startend fill:#F5EBFF,stroke:#BE8FED,stroke-width:2px;
classDef process fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px;
classDef decision fill:#FFF6CC,stroke:#FFBC52,stroke-width:2px;
A([开始]):::startend --> B{是否有数据交换}:::decision
B -- 是 --> C(配置路径):::process
B -- 否 --> D(节点空闲):::process
C --> E(查询邻居请求路由):::process
E --> F{是否到达目的地}:::decision
F -- 是 --> G(定义路径):::process
F -- 否 --> H(增加跳数计数器,重复消息):::process
H --> E
G --> I([结束]):::startend
D --> B
5. 传输层安全(TLS)
5.1 TLS 概述
链路层协议通常提供一些基本的安全机制,使用对称密钥(如 AES)来保证连接到特定网络的客户端的身份验证和数据加密。在大多数情况下,链路层的身份验证足以保证基本的安全级别。然而,LR - WPAN 网络栈中常用的预共享、已知密钥可能容易受到多种攻击,如果密钥泄露,攻击者可以解密之前在同一链路上捕获的任何流量。在其他场景中,仅加密不足以保证另一方是其声称的身份,或数据在传输过程中未被篡改。
参与物联网分布式系统的设备需要实现更高级别的安全,特别是在不保护内存的嵌入式设备中,任何后门都意味着攻击者可以控制设备并检索所有敏感信息,如用于与远程系统通信的身份验证和加密的私钥。
TLS 是一组旨在通过标准 TCP/IP 套接字提供安全通信的加密协议,主要关注分布式系统中安全通信的三个关键要求:
- 保密性:通过使用对称加密确保参与方之间通信的保密性。TLS 定义了旨在生成一次性对称密钥的加密技术,这些密钥在生成它们的会话结束时失效。
- 身份验证:使用公钥加密对挑战负载进行签名和验证,以验证通信参与方的身份。由于非对称密钥的特性,只有拥有秘密私钥的一方能够对负载进行签名,而任何人都可以通过使用签名消息的公钥对应物检查签名来验证签名的真实性。
- 完整性:使用消息摘要验证消息在传输过程中未被修改。
5.2 wolfSSL 实现
有一些开源实现可用于嵌入式市场,以启用标准加密算法和安全套接字通信策略。其中,免费开源软件库 wolfSSL 提供了最完整和最新的实现。该库提供了 TLS 和 DTLS 的最新标准版本,专为小型嵌入式系统的性能和可靠性而设计,包括支持许多为系统安全设计的嵌入式平台的硬件加速器和随机数生成器。
wolfSSL 在其核心库(wolfCrypt)中实现了加密原语,并将它们分组到 TLS 套接字使用的密码套件中,这些套件可以轻松集成到裸机网络应用程序和任何提供传输套接字通信 API 的嵌入式操作系统中。这些加密原语针对嵌入式设备进行了优化,在最关键的性能操作中使用汇编代码以获得最佳性能。
为微控制器设计的 TLS/SSL 库的主要优点是它实现了与互联网上任何 PC 或服务器相同的协议,但代码大小仅为其一小部分,并且在最昂贵的加密操作期间始终控制资源使用(如内存使用)。采用支持前沿加密算法的 TLS 库可以与物联网网络的经典 IT 基础设施组件中实施的安全措施完美集成。在云端,供远程嵌入式系统访问的服务应允许选择基于椭圆曲线的更高效密码套件,因为传统的基于 RSA 的公钥加密需要更大的密钥和复杂的计算才能达到相同的安全级别。TLS 1.3 中包含了新的基于公钥的加密标准,如 Curve22519。
分布式系统与物联网架构中的网络通信技术(续)
6. 不同路由协议的选择与应用
在构建网状网络时,选择合适的路由协议至关重要,这取决于网络的具体需求。以下是不同类型路由协议的适用场景分析:
| 协议类型 | 适用场景 | 优缺点 |
| ---- | ---- | ---- |
| 主动动态路由协议 | 适用于始终在线、需要实时响应的嵌入式系统。例如,工业自动化中的传感器网络,要求网络随时可用,对拓扑变化的反应时间较短。 | 优点是路由表始终更新到网络的最新已知状态,每个节点随时知道到每个可能目的地的最佳路由;缺点是需要定期广播消息来更新网络节点及其邻居的状态,消耗一定的网络资源。 |
| 被动动态路由协议 | 适合具有间歇性数据交换、电池供电节点的网络。比如,一些野外环境监测的传感器节点,在没有数据传输时可以处于空闲状态以节省电量。 | 优点是节点在无数据交换时可以空闲,节省功率,对拓扑变化的反应可能更快;缺点是通信的第一条消息可能会有额外延迟,因为需要按需形成动态路由。 |
对于 picoTCP 而言,它支持的 OLSR 和 AODV 协议为不同需求的网络提供了选择。如果要启用 OLSR 协议,只需编译支持 OLSR 的协议栈,然后通过以下代码添加参与网状网络定义的设备:
pico_olsr_add(struct pico_device *dev);
若要启用 AODV 网络,使用以下代码添加接口:
pico_aodv_add(struct pico_devices *dev);
在实际应用中,还可以根据网络的具体情况对路由协议进行优化。例如,在 OLSR 协议中,可以考虑除跳数之外的其他参数,如无线链路质量(信噪比、接收信号强度等),以选择更优的路由。
7. 套接字通信的优化与实践
在套接字通信中,不同的 TCP/IP 栈(如 lwIP 和 picoTCP)提供了不同的接口和机制。为了提高通信效率和性能,可以采取以下优化措施:
7.1 回调函数的合理使用
lwIP 和 picoTCP 都通过回调函数来处理网络事件。在使用回调函数时,应确保其逻辑简洁高效,避免在回调函数中执行耗时的操作,以免影响网络响应速度。例如,在 picoTCP 的
wakeup
回调函数中,应尽快处理事件,避免阻塞其他操作。
7.2 资源管理
对于套接字资源,要进行合理的分配和释放。在创建套接字后,当不再使用时,应及时关闭套接字以释放资源。例如,在 picoTCP 中,使用完套接字后可以调用相应的关闭函数。
7.3 错误处理
在套接字通信过程中,可能会出现各种错误,如连接失败、数据传输错误等。应在代码中添加完善的错误处理机制,以确保系统的稳定性。例如,在 lwIP 的
tcp_bind
和
tcp_listen
函数调用后,检查返回值是否为错误码,若出现错误则进行相应的处理。
以下是一个简单的错误处理示例:
err_t err;
struct tcp_pcb *pcb = tcp_new();
if (pcb != NULL) {
err = tcp_bind(pcb, ipaddr, port);
if (err != ERR_OK) {
// 处理绑定错误
tcp_close(pcb);
return;
}
err = tcp_listen(pcb);
if (err != ERR_OK) {
// 处理监听错误
tcp_close(pcb);
return;
}
}
8. 安全通信的重要性与实践
在物联网系统中,安全通信至关重要。TLS 协议为数据传输提供了保密性、身份验证和完整性保障。以下是在实际应用中实现安全通信的步骤:
8.1 选择合适的 TLS 库
如前文所述,wolfSSL 是一个不错的选择,它提供了最新的 TLS 和 DTLS 标准版本,并且针对嵌入式设备进行了优化。
8.2 配置 TLS 连接
在使用 wolfSSL 时,需要进行一系列的配置,包括选择密码套件、加载证书等。以下是一个简单的配置示例:
#include <wolfssl/options.h>
#include <wolfssl/wolfcrypt/settings.h>
#include <wolfssl/ssl.h>
// 初始化 wolfSSL
wolfSSL_Init();
// 创建 SSL 上下文
WOLFSSL_CTX* ctx = wolfSSL_CTX_new(wolfTLSv1_3_client_method());
if (ctx == NULL) {
// 处理上下文创建失败
return;
}
// 加载证书
if (wolfSSL_CTX_load_verify_locations(ctx, "ca-cert.pem", NULL) != SSL_SUCCESS) {
// 处理证书加载失败
wolfSSL_CTX_free(ctx);
return;
}
// 创建 SSL 对象
WOLFSSL* ssl = wolfSSL_new(ctx);
if (ssl == NULL) {
// 处理 SSL 对象创建失败
wolfSSL_CTX_free(ctx);
return;
}
// 连接到服务器
if (wolfSSL_connect(ssl) != SSL_SUCCESS) {
// 处理连接失败
wolfSSL_free(ssl);
wolfSSL_CTX_free(ctx);
return;
}
// 进行数据传输
// ...
// 关闭连接
wolfSSL_shutdown(ssl);
wolfSSL_free(ssl);
wolfSSL_CTX_free(ctx);
wolfSSL_Cleanup();
8.3 密钥管理
在 TLS 通信中,密钥的管理非常重要。要确保私钥的安全存储,避免泄露。可以使用硬件安全模块(HSM)来存储和管理私钥,提高安全性。
9. 总结与展望
在分布式系统和物联网架构中,网络通信技术涵盖了路由配置、套接字通信、无连接协议、网状网络和动态路由以及安全通信等多个方面。不同的技术和协议适用于不同的场景,需要根据具体需求进行选择和优化。
随着物联网的不断发展,对网络通信的要求也越来越高。未来,我们可以期待更高效、更安全的网络通信技术的出现。例如,更先进的动态路由协议可以更好地适应复杂多变的网络拓扑;更强大的安全机制可以进一步保障数据的安全传输。同时,随着硬件技术的不断进步,嵌入式设备的性能将不断提高,为网络通信技术的发展提供更坚实的基础。
graph LR
classDef startend fill:#F5EBFF,stroke:#BE8FED,stroke-width:2px;
classDef process fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px;
classDef decision fill:#FFF6CC,stroke:#FFBC52,stroke-width:2px;
A([开始]):::startend --> B(选择路由协议):::process
B --> C{是否为主动协议}:::decision
C -- 是 --> D(配置主动路由):::process
C -- 否 --> E(配置被动路由):::process
D --> F(创建套接字):::process
E --> F
F --> G(配置安全通信):::process
G --> H(进行数据传输):::process
H --> I{是否完成通信}:::decision
I -- 否 --> H
I -- 是 --> J(关闭连接):::process
J --> K([结束]):::startend
通过合理应用这些网络通信技术,并不断进行优化和创新,我们可以构建更加稳定、高效、安全的分布式系统和物联网架构。
物联网中网络通信关键技术解析
超级会员免费看
1243

被折叠的 条评论
为什么被折叠?



