携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第20天,点击查看活动详情
今天我们接着昨天的主题来学习一下 Rust 中的网络编程。上节中我们学习了使用 std::net 构建一般网络程序的方法。今天我们将主要学习下网络应用开发中的问题以及常见的网络通讯模型。
01-网络编程中常见的问题
开发网络应用时,需要正视几个问题:
- 网络是不可靠的,应对方式是使用 TCP 及构建在 TCP 之上的协议来保证可靠性;
- 网络的延迟可能非常大,应对方式是使用队列和超时;
- 网络的带宽是有限的,应对方式是使用二进制结构、压缩算法以及某些技巧,减少带宽的使用;
- 网络是不安全的,应对方式是需要使用 TLS 或 noise 协议等安全协议保护传输中的数据。
02-主要的网络通讯模型
主要的网络通讯模型:
-
双向通讯,例如基于 TCP、WebSocket 的 client / server 就是在全双工模式下运行的;
-
请求响应,client 请求,server 响应,运行在半双工模式下;缺点就是应用层可能会发生队头阻塞;
-
控制平面、数据平面分离,客户端先与服务端建立控制连接,一个长连接,一直存在,直到交互终止;然后客户端与服务端按需建立临时的数据连接,用来传输大容量数据,在传输完毕后关闭。例如,FTP、多媒体通讯协议 SIP 都是基于这种模型;
而且,HTTP/2 和基于 HTTP/2 的 Yamux 协议,虽然运行在同一个 TCP 连接之上,但是在应用层构建了类似的控制平面和数据平面;
-
P2P 网络,客户端/服务端模型天然是中心化的,P2P 是去中心化的,点对点网络。
P2P 网路中节点间的连接需要承载很多协议,例如节点发现、节点路由、内容发现以及应用层协议,还有保证连接安全性的协议 noise等;
P2P 协议的连接往往在一个 TCP 连接中,使用类似 Yamux 的多路复用协议来承载很多其他协议。
03-Rust 下如何开发基于 P2P 网络的应用
Rust 下主要使用第三方库 libp2p 来处理 P2P 网络。
#[derive(NetworkBehaviour)]
#[behaviour(event_process = true)]
struct ChatBehavior {
floodsub: Floodsub, // floodpub 做消息传播
mdns: Mdns, // MDNS 做节点发现
}
处理事件:
impl NetworkBehaviourEventProcess<FloodsubEvent> for ChatBehavior {
/// 处理消息传播事件
fn inject_event(&mut self, event: FloodsubEvent) {
if let FloodsubEvent::Message(msg) = event {
let text = String::from_utf8_lossy(&msg.data);
println!("{:?}: {:?}", msg.source, text)
}
}
}
impl NetworkBehaviourEventProcess<MdnsEvent> for ChatBehavior {
/// 处理节点发现事件
fn inject_event(&mut self, event: MdnsEvent) {
match event {
// 节点上线
MdnsEvent::Discovered(list) => {
for (id, addr) in list {
println!("Got peer: {} with addr {}", &id, &addr);
self.floodsub.add_node_to_partial_view(id);
}
},
// 节点下线
MdnsEvent::Expired(list) => {
for (id, addr) in list {
println!("Removed peer: {} with addr {}", &id, &addr);
self.floodsub.remove_node_from_partial_view(&id);
}
}
}
}
}
本节课程链接《29|网络开发(下):如何使用Rust处理网络请求?》