前言
ws-rs实现了MIO的WebSockets RFC6455标准。它允许在单个线程上处理多个连接,甚至可以在同一线程上生成新的客户端连接。这使得WebSockets非常快速且资源高效。API设计抽象了WebSocket协议的底层部分,使开发者可以专注于应用程序代码,而不必担心协议的一致性。
一、创建项目
首先还是老规矩,先创建本期内容所需要的工程,由于本期是通信类的Websocket,因此需要准备两个工程,一个server,一个client。
1. 创建服务端项目
cargo new ws_rs_server
然后添加依赖,将以下内容加入到工程Cargo.toml
中,如下图所示
ws = "0.9.2" env_logger = "0.6"
2. 创建客户端项目
cargo new ws_rs_client
然后添加依赖,同样加上刚才的依赖,
ws = "0.9.2" env_logger = "0.6"
二、编写测试代码
1.服务端
首先是服务端部分的代码,使用该库需要引入ws::listen
use ws::listen;
然后在main中调用,实现监听操作,例如
// 监听地址并为每个连接调用闭包 if let Err(error) = listen("127.0.0.1:3012", |out| { // 处理程序需要获取out的所有权,因此我们使用move move |msg| { // 处理在此连接上接收的消息 println!("服务器收到消息 '{}'. ", msg); // 使用输出通道发送消息 out.send(msg) } }) { // 通知用户故障 println!("创建Websocket失败,原因: {:?}", error); }
listen需要传入两个参数,一个是监听的地址和端口,这里使用的是127.0.0.1:3012
,然后就是个匿名函数,传入out
,获取out
的所有权,然后在其内部使用move
关键字自动捕获msg
,其中msg
就是服务端收到的消息,在服务端开发中,主要处理的就是这部分内容。
这里处理客户端消息逻辑很简单,
- 输出从客户端接收到的消息
- 把客户端发送的消息返回
也就是说,实际上就是个echo,但是还是有点区别的,这个只返回一次。
2.客户端
客户端部分需要引入connect
用来连接服务端,引入CloseCode
来关闭连接。
use ws::{connect, CloseCode};
然后就是在main
中调用,首先是connect
,其调用方式和server
的listen
是一样的,需要传入两个参数,
- wss连接,例如
ws://127.0.0.1:3012
,其中ws://
表示使用websocket协议,127.0.0.1
是ip地址,3012
是端口,值得注意的是要和server相对应,否则会连接失败 - 一个闭包匿名函数,传入
out
客户端的闭包匿名函数主要要做两件事,
- 发送消息到服务端
- 处理来自服务端的消息
这里的示例代码如下
// 连接到url并调用闭包 if let Err(error) = connect("ws://127.0.0.1:3012", |out| { // 将WebSocket打开时要发送的消息排队 if out.send("Hello WebSocket").is_err() { println!("Websocket无法初始消息排队") } else { println!("Client 发送消息 'Hello WebSocket'. ") } // 处理程序需要获取out的所有权,因此我们使用move move |msg| { // 处理在此连接上接收的消息 println!("Client 收到消息 '{}'. ", msg); // 关闭连接 out.close(CloseCode::Normal) } }) { // 通知用户故障 println!("Failed to create WebSocket due to: {:?}", error); }
可以看到,这段代码的逻辑是,
- 先发送
Hello WebSocket
到服务端,同时判断发送过程中是否有错,如果发送出错,则输出Websocket无法初始消息排队
,发送成功的情况下在客户端界面输出Client 发送消息 'Hello WebSocket'.
- 处理来自服务端的消息,可以看到这里和server是高度相似的,收到消息后,输出
Client 收到消息 '{}'.
,其中{}
是服务端消息的占位符,收到消息后直接断开服务端的连接
三、 运行效果
运行服务端
运行客户端
总结
本期学习了Rust的websocket通信框架ws-rs,并且编写了两个官方提供的小案例,通过本期内容的学习,你已学会了使用Rust来编写websocket程序,这个在开发中是具有里程碑意义的,你写的程序从此可以联网进行数据传输,使得程序给用户带来更好的体验,并且会让你的程序变得丰富多彩。
完整代码
服务端
use ws::listen; fn main() { // 初始化日志 env_logger::init(); // 监听地址并为每个连接调用闭包 if let Err(error) = listen("127.0.0.1:3012", |out| { // 处理程序需要获取out的所有权,因此我们使用move move |msg| { // 处理在此连接上接收的消息 println!("服务器收到消息 '{}'. ", msg); // 使用输出通道发送消息 out.send(msg) } }) { // 通知用户故障 println!("创建Websocket失败,原因: {:?}", error); } }
客户端
use ws::{connect, CloseCode}; fn main() { // 初始化日志 env_logger::init(); // 连接到url并调用闭包 if let Err(error) = connect("ws://127.0.0.1:3012", |out| { // 将WebSocket打开时要发送的消息排队 if out.send("Hello WebSocket").is_err() { println!("Websocket无法初始消息排队") } else { println!("Client 发送消息 'Hello WebSocket'. ") } // 处理程序需要获取out的所有权,因此我们使用move move |msg| { // 处理在此连接上接收的消息 println!("Client got message '{}'. ", msg); // 关闭连接 out.close(CloseCode::Normal) } }) { // 通知用户故障 println!("Failed to create WebSocket due to: {:?}", error); } }
本人创建了一起学Rust
社区,欢迎各位对rust感兴趣的朋友加入。
http://t.csdn.cn/AsEZ9