#stream #async #web-api #tcp-connection #async-io

ws_stream_wasm

WASM 中使用 WebSocket 的便利库

18 个版本

0.7.4 2023年1月29日
0.7.3 2021年6月28日
0.7.0 2021年2月18日
0.7.0-beta.12020年11月3日
0.1.0 2019年7月19日

#5 in WebSocket

Download history 53899/week @ 2024-04-20 50606/week @ 2024-04-27 45989/week @ 2024-05-04 51997/week @ 2024-05-11 51647/week @ 2024-05-18 51145/week @ 2024-05-25 53808/week @ 2024-06-01 54195/week @ 2024-06-08 56856/week @ 2024-06-15 58249/week @ 2024-06-22 49831/week @ 2024-06-29 44450/week @ 2024-07-06 46762/week @ 2024-07-13 49080/week @ 2024-07-20 47505/week @ 2024-07-27 46857/week @ 2024-08-03

198,437 每月下载量
用于 361 个 Crates (直接使用 32 个)

Unlicense 许可

54KB
778

ws_stream_wasm

standard-readme compliant Build Status Docs crates.io

WASM 中使用 WebSocket 的便利库

直接使用 web-sys 绑定的 WebSocket 不太方便。这个 Crates 旨在解决这个问题。浏览器不能创建直接的 TCP 连接,通过在 WebSocket 上放置 AsyncRead/AsyncWrite,我们可以在浏览器内部使用任何异步字节流的工作接口。该 Crates 有两种主要类型。存在 WsMeta 类型是为了在将 WsStream 传递给拥有流的所有权组合器的同时访问 Web API。

功能

  • WsMeta: 对 web_sys::WebSocket 的包装。
  • WsMessage: WebSocket 消息的简单 Rust 表示。
  • WsStream: WsMessagefutures Sink/Stream。它还有一个方法 into_io(),允许你获取一个实现了 AsyncRead/AsyncWrite/AsyncBufRead (在 tokio 版本中通过 tokio_io 功能) 的包装器。
  • WsEventWsMeta 可以通过 pharos 观察事件(主要用于连接关闭)。

注意:此包仅在WASM上工作。如果您需要实现 AsyncRead/AsyncWrite 的服务器端等效功能,请查看 ws_stream_tungstenite

缺少的功能

  • 没有自动重连
  • 并非所有功能都经过彻底测试。特别是,我对扩展和子协议的使用很少。我使用的 Tungstenite(用于服务器端和自动化测试)不支持这些功能,这使得编写单元测试变得困难。

目录

安装

使用 cargo addcargo add ws_stream_wasm

使用 cargo yaml

dependencies:

  ws_stream_wasm: ^0.7

在 Cargo.toml 中

[dependencies]

   ws_stream_wasm = "0.7"

升级

升级时请查看 变更日志

依赖

此包的依赖项很少。Cargo 会自动为您处理依赖项。

有一个可选功能。启用 tokio_io 功能会导致从 WsStream::into_io 返回的 WsIo 实现tokio版本的AsyncRead/AsyncWrite。

使用方法

集成测试展示了大多数功能的使用情况。示例目录目前没有包含任何有趣的示例。

从编译器的角度来看,此库中的类型是 Send + Sync。这样,您可以将其与也适用于WASM的通用库一起使用,这些库需要连接为 Send/Sync。目前WASM没有线程,而我们使用的底层类型大多数不是 Send。目前的解决方案是使用 send_wrapper::SendWrapper。如果它在创建它的线程之外被解引用,则会引发恐慌。您必须考虑这些类型不是 Send,但在WASM上,将其传递给需要 Send 的API是安全的,因为没有太多的多线程支持。因此,将其传递给bindgen executor将是安全的。然而,使用webworkers时,您仍然可以创建额外的线程。责任在于您确保不要尝试在不同的线程上使用Web Api。

您想要使用的主要入口点,例如连接,是 WsMeta::connect

基本事件示例

use
{
   ws_stream_wasm       :: *                        ,
   pharos               :: *                        ,
   wasm_bindgen         :: UnwrapThrowExt           ,
   wasm_bindgen_futures :: futures_0_3::spawn_local ,
   futures              :: stream::StreamExt        ,
};

let program = async
{
   let (mut ws, _wsio) = WsMeta::connect( "ws://127.0.0.1:3012", None ).await

      .expect_throw( "assume the connection succeeds" );

   let mut evts = ws.observe( ObserveConfig::default() ).expect_throw( "observe" );

   ws.close().await;

   // Note that since WsMeta::connect resolves to an opened connection, we don't see
   // any Open events here.
   //
   assert!( evts.next().await.unwrap_throw().is_closing() );
   assert!( evts.next().await.unwrap_throw().is_closed () );
};

spawn_local( program );

过滤事件示例

这展示了如何过滤事件。此功能来自 pharos,我们使用它来使 WsMeta 可观察。

use
{
   ws_stream_wasm       :: *                        ,
   pharos               :: *                        ,
   wasm_bindgen         :: UnwrapThrowExt           ,
   wasm_bindgen_futures :: futures_0_3::spawn_local ,
   futures              :: stream::StreamExt        ,
};

let program = async
{
   let (mut ws, _wsio) = WsMeta::connect( "ws://127.0.0.1:3012", None ).await

      .expect_throw( "assume the connection succeeds" );

   // The Filter type comes from the pharos crate.
   //
   let mut evts = ws.observe( Filter::Pointer( WsEvent::is_closed ).into() ).expect_throw( "observe" );

   ws.close().await;

   // Note we will only get the closed event here, the WsEvent::Closing has been filtered out.
   //
   assert!( evts.next().await.unwrap_throw().is_closed () );
};

spawn_local( program );

API

API 文档可以在 docs.rs 上找到。

参考

理解WebSocket以及浏览器如何处理它们的参考文档有

贡献

请查看贡献指南

测试

为了测试,我们需要后端服务器将数据回显给测试。这些在ws_stream_tungstenite crate中。

git clone https://github.com/najamelan/ws_stream_tungstenite
cd ws_stream_tungstenite
cargo run --example echo --release

# in a different terminal:
cargo run --example echo_tt --release -- "127.0.0.1:3312"

# the second server is pure async-tungstenite without ws_stream_tungstenite wrapping it in AsyncRead/Write. This
# is needed for testing a WsMessage::Text because ws_stream_tungstenite only does binary.

# in a third terminal, in ws_stream_wasm you have different options:
wasm-pack test --firefox [--headless] [--release]
wasm-pack test --chrome  [--headless] [--release]

一般来说,Chrome运行速度更快。在浏览器中运行(不使用--headless)时,你会在控制台中获得跟踪日志,这有助于调试。在Chrome中,您需要在控制台中启用详细输出,否则只会报告信息和更高级别的信息。

行为准则

公民行为准则的第4点“不可接受的行为”中描述的任何行为都不受欢迎,可能会让您被禁止。如果任何人都未能尊重这些/您的限制,包括项目的维护者和管理员,您有权指出。

许可

未授权许可

依赖

~7-11MB
~210K SLoC