【一起学Rust | 框架篇 | ws-rs框架】属于Rust的Websocket框架——ws-rs


前言

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就是服务端收到的消息,在服务端开发中,主要处理的就是这部分内容。

这里处理客户端消息逻辑很简单,

  1. 输出从客户端接收到的消息
  2. 把客户端发送的消息返回

也就是说,实际上就是个echo,但是还是有点区别的,这个只返回一次。

2.客户端

客户端部分需要引入connect用来连接服务端,引入CloseCode来关闭连接。

use ws::{connect, CloseCode};

然后就是在main中调用,首先是connect,其调用方式和serverlisten是一样的,需要传入两个参数,

  1. wss连接,例如ws://127.0.0.1:3012,其中ws://表示使用websocket协议,127.0.0.1是ip地址,3012是端口,值得注意的是要和server相对应,否则会连接失败
  2. 一个闭包匿名函数,传入out

客户端的闭包匿名函数主要要做两件事,

  1. 发送消息到服务端
  2. 处理来自服务端的消息

这里的示例代码如下

 // 连接到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);
    }

可以看到,这段代码的逻辑是,

  1. 先发送Hello WebSocket到服务端,同时判断发送过程中是否有错,如果发送出错,则输出Websocket无法初始消息排队,发送成功的情况下在客户端界面输出Client 发送消息 'Hello WebSocket'.
  2. 处理来自服务端的消息,可以看到这里和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 
使用 GTK-rs 库需要先安装 GTK+3,可以在 Linux 系统下通过包管理器安装,也可以在 Windows 和 macOS 下从官网下载安装程序进行安装。 安装 GTK+3 后,可以在 Rust 项目中添加 gtk 和 gdk 两个依赖: ```toml [dependencies] gtk = "0.9" gdk = "0.9" ``` 然后在 Rust 代码中引入 gtk 和 gdk 库: ```rust extern crate gtk; extern crate gdk; ``` 在 GTK-rs 中,主要有两种方式创建 GUI 窗口:Builder 和手动创建。下面分别介绍这两种方式。 ### 使用 Builder 创建 GUI 窗口 使用 Builder 可以通过 XML 文件描述 GUI 界面,然后使用 Rust 代码加载并显示窗口。以下是一个简单的例子: ```xml <?xml version="1.0" encoding="UTF-8"?> <interface> <object class="GtkWindow" id="main_window"> <property name="title">Hello, World!</property> <property name="default-width">400</property> <property name="default-height">300</property> <child> <object class="GtkLabel" id="label"> <property name="label">Hello, World!</property> </object> </child> </object> </interface> ``` 在 Rust 代码中,可以使用 gtk::Builder 加载并显示窗口: ```rust use gtk::prelude::*; use gtk::{Builder, Window}; fn main() { if let Err(err) = gtk::init() { eprintln!("Failed to initialize GTK: {}", err); return; } let glade_src = include_str!("path/to/glade/file.glade"); let builder = Builder::from_string(glade_src); let window: Window = builder.get_object("main_window").unwrap(); window.show_all(); gtk::main(); } ``` ### 手动创建 GUI 窗口 手动创建 GUI 窗口需要在 Rust 代码中定义窗口和窗口中的组件,以下是一个简单的例子: ```rust use gtk::prelude::*; use gtk::{Window, WindowType, Label}; fn main() { if let Err(err) = gtk::init() { eprintln!("Failed to initialize GTK: {}", err); return; } let window = Window::new(WindowType::Toplevel); window.set_title("Hello, World!"); window.set_default_size(400, 300); let label = Label::new(Some("Hello, World!")); window.add(&label); window.show_all(); gtk::main(); } ``` 以上代码中,创建了一个顶层窗口和一个标签组件,将标签添加到窗口中并显示窗口。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

广龙宇

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值