ITADN
Gelbpunkt/tokio-websockets
Gelbpunkt/tokio-websockets · 文件 下载 ZIP
文件最后提交记录最后更新时间
README.md
以下内容由 AI 翻译,如有问题请点此提交 issue 反馈

tokio-websockets

Crates.io GitHub Workflow Status (with event) Documentation Chat

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

为什么使用 tokio-websockets?

  • 基于 tokio-util 构建,旨在从底层与 tokio 配合使用
  • 依赖项极少:基础部分仅需要:
    • tokiotokio-utilbytesfutures-corefutures-sinksimdutf8
    • SHA1 后端,例如 sha1_smol(参见 Feature flags
  • 丰富的功能选项,可根据任何项目定制依赖项(参见 Feature flags
  • 支持 SIMD 进行帧(解)掩码处理以及加速的 UTF-8 验证(参见 SIMD
  • 严格遵循 WebSocket 规范,默认情况下通过 Autobahn 测试套件 且无需放宽限制 by default
  • 支持 TLS
  • 可复用的 TLS 连接器
  • 使用生态系统中广为人知的 crate 作为类型,例如客户端中的 http 中的 Uri
  • 由于使用 Bytes 作为负载存储,消息可低成本克隆
  • 针对性能进行了调优(参见 基准测试

Feature flags

tokio-websockets 中的 Feature flags 旨在允许根据您的需求进行定制。

  • 使用 nightly 编译器时,nightly 功能将在更多目标上启用 SIMD 加速的掩码处理和 UTF-8 验证(参见 SIMD
  • client 启用一个小型客户端实现
  • server 启用一个小型服务器实现

TLS 通过以下任一 Feature flag 支持:

rustls-*-rootsrustls-platform-verifier 功能需要为 rustls 安装全局 crypto provider,您可以通过在所选的 provider 上调用 CryptoProvider::install_default() 来实现。

需要一个 SHA1 实现,通常由 TLS 实现或其 crypto provider 提供:

  • 如果启用了 ringaws_lc_rs 功能,则使用 ringaws_lc_rs(在同时用于 rustls 时推荐)
  • openssl 功能将使用 openssl,在大多数带有 native-tls 的 Linux/BSD 系统上通常更受青睐
  • 如果不需要 TLS,可以使用 sha1_smol 功能作为回退方案

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

  • fastrand 可以作为 PRNG 使用
  • getrandom 可以作为密码学安全的 RNG 使用
  • 启用 nightly 功能后,std::random 可以作为密码学安全的 RNG 使用
  • rand 可以作为 fastrand 的替代方案,如果它已经在依赖树中,则应优先使用

SIMD

tokio-websockets 利用 SIMD 来加速消息的(去)掩码处理和 UTF-8 验证。

架构指令集(非)掩码UTF-8 验证
aarch64NEON
armNEON✅ (on nightly)✅ (on nightly)
loongarch64LSX✅ (on nightly)
loongarch64LASX✅ (on nightly)
powerpcAltiVec✅ (on nightly)
powerpc64AltiVec✅ (on nightly)
powerpc64leAltiVec✅ (on nightly)
s390xz13 vectors✅ (on nightly)
x86_64SSE2
x86_64AVX2
x86_64AVX512

示例

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

一个简单的 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 (_request, 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(())
}

使用 rustls 和以 aws_lc_rs 作为加密提供程序的基本客户端:

use futures_util::{SinkExt, StreamExt};
use http::Uri;
use tokio_websockets::{ClientBuilder, Error, Message};

#[tokio::main]
async fn main() -> Result<(), Error> {
    // Will set the default crypto provider for libraries which configure rustls
    rustls::crypto::aws_lc_rs::default_provider()
        .install_default()
        .unwrap();

    // Connecting to a echo server with TLS set up
    let uri = Uri::from_static("wss://ws.vi-server.org/mirror");
    let (mut client, _) = ClientBuilder::from_uri(uri).connect().await?;

    // Print out if its a plain or TLS socket
    // Requires a TLS feature to be turned on to not be plain
    println!("{:?}", client.get_ref());

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

    let msg = client.next().await;

    println!("Got echo response: {msg:?}");

    client.close().await?;

    Ok(())
}

MSRV

当前所有功能组合的 MSRV 为 Rust 1.89。

注意事项 / 限制 / 待办

目前不支持 WebSocket 压缩。