#websocket-server #performance #high #tokio-util #byte #tls

tokio-websockets

基于 tokio-util 的高性能、严格 WebSocket 实现

16 个版本 (8 个破坏性更新)

0.9.0 2024 年 8 月 4 日
0.8.3 2024 年 5 月 24 日
0.8.2 2024 年 4 月 16 日
0.7.0 2024 年 2 月 27 日
0.2.0 2022 年 12 月 6 日

#7 in WebSocket

Download history 762/week @ 2024-05-04 930/week @ 2024-05-11 1054/week @ 2024-05-18 1242/week @ 2024-05-25 1052/week @ 2024-06-01 739/week @ 2024-06-08 834/week @ 2024-06-15 794/week @ 2024-06-22 524/week @ 2024-06-29 854/week @ 2024-07-06 879/week @ 2024-07-13 908/week @ 2024-07-20 1538/week @ 2024-07-27 1767/week @ 2024-08-03 1526/week @ 2024-08-10 1202/week @ 2024-08-17

6,182 每月下载量
用于 4 crates

MIT 许可证

140KB
2.5K SLoC

tokio-websockets

Crates.io GitHub Workflow Status (with event) Documentation

基于 tokio-util 的高性能、严格 WebSocket 实现。

为什么使用 tokio-websockets?

  • 使用 tokio-util 构建,从一开始就打算与 tokio 一起使用
  • 最小依赖:基础库只需要
    • tokio, tokio-util, bytes, futures-core, futures-sink
    • SHA1 后端,例如 sha1_smol(见 功能标志
  • 大量功能,可根据项目需求定制依赖(见 功能标志
  • SIMD 支持:AVX2、SSE2 或 NEON 用于帧(解)屏蔽和加速 UTF-8 验证
  • 严格遵守 WebSocket 规范,默认情况下通过 Autobahn 测试套件,无需放宽条件 by default
  • 支持 TLS
  • 可重用的 TLS 连接器
  • 使用生态系统中的广泛知名 crates 进行类型,例如客户端中的 Uri 来自 http
  • 由于使用 Bytes 作为有效载荷存储,因此消息克隆成本低
  • 针对性能进行调优(见 基准测试

功能标志

在 tokio-websockets 中添加功能标志是为了使其满足您的需求。

  • simd 将启用 AVX2、SSE2 或 NEON 加速屏蔽和 UTF-8 验证。此外,当使用 nightly 编译器时,启用 nightly 功能也将启用 AVX512 加速屏蔽
  • client 启用一个微型客户端实现
  • server 启用一个微型服务器实现

通过以下任一功能标志支持TLS:

使用 rustls-*-rootsrustls-platform-verifier 功能需要为 rustls 提供加密提供者。您可以选择启用 aws_lc_rs(可选地,通过 fips 功能符合FIPS规范)或 ring 功能来将这些crate用作提供者,然后使用 TlsConnector::new(),或者使用 TlsConnector::new_rustls_with_crypto_provider() 带入自己的。

需要一种SHA1实现,通常由TLS实现提供

  • 如果启用了 ringaws_lc_rs 功能,则使用 ringaws_lc_rs
  • 启用 openssl 功能将使用 openssl,通常在大多数Linux/BSD系统上使用 native-tls 时首选
  • 如果没有需要TLS,可以使用 sha1_smol 功能作为后备

client 功能需要启用一个随机数生成器

  • fastrand 可以用作 PRNG
  • getrandom 可以用作加密安全的RNG
  • rand 可以作为 fastrand 的替代品,如果它已经在依赖树中,则应首选

示例

这是一个没有适当错误处理的简单WebSocket回显服务器。

更多示例可以在示例文件夹中找到。

use futures_util::{SinkExt, StreamExt};
use http::Uri;
use tokio::net::TcpListener;
use tokio_websockets::{ClientBuilder, Error, Message, ServerBuilder};

#[tokio::main]
async fn main() -> Result<(), Error> {
  let listener = TcpListener::bind("127.0.0.1:3000").await?;

  tokio::spawn(async move {
    while let Ok((stream, _)) = listener.accept().await {
      let mut ws_stream = ServerBuilder::new()
        .accept(stream)
        .await?;

      tokio::spawn(async move {
        // Just an echo server, really
        while let Some(Ok(msg)) = ws_stream.next().await {
          if msg.is_text() || msg.is_binary() {
            ws_stream.send(msg).await?;
          }
        }

        Ok::<_, Error>(())
      });
    }

    Ok::<_, Error>(())
  });

  let uri = Uri::from_static("ws://127.0.0.1:3000");
  let (mut client, _) = ClientBuilder::from_uri(uri).connect().await?;

  client.send(Message::text("Hello world!")).await?;

  while let Some(Ok(msg)) = client.next().await {
    if let Some(text) = msg.as_text() {
      assert_eq!(text, "Hello world!");
      // We got one message, just stop now
      client.close().await?;
    }
  }

  Ok(())
}

MSRV

当前所有功能组合的MSRV是Rust 1.79。

注意事项/限制/待办事项

当前不支持WebSocket压缩。

依赖项

~2–29MB
~613K SLoC