首页    新闻    小组    威客    人才    下载    博客    代码贴    在线编程    论坛
Deno 开源 fastwebsockets,Rust 编写的高性能 WebSocket 协议实现
2023年5月3日 17:22 | 阅读 1816 次

Deno 开源了宣称速度极快的 fastwebsockets —— Rust 编写的高性能 WebSocket 协议 (RFC6455 WebSocket) 实现。

fastwebsockets 核心特性

  • 可用作原生 WebSocket 帧解析器、成熟的客户端/服务器
use fastwebsockets::{Frame, OpCode, WebSocket};

async fn handle_client(
  mut socket: TcpStream,
) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
  handshake(&mut socket).await?;

  let mut ws = WebSocket::after_handshake(socket);
  ws.set_writev(true);
  ws.set_auto_close(true);
  ws.set_auto_pong(true);

  loop {
    let frame = ws.read_frame().await?;

    match frame {
      OpCode::Close => break,
      OpCode::Text | OpCode::Binary => {
        let frame = Frame::new(true, frame.opcode, None, frame.payload);
        ws.write_frame(frame).await?;
      }
    }
  }

  Ok(())
}
  • 与 Hyper 集成

启用upgrade功能以进行服务器端升级,以及与客户端握手。

use fastwebsockets::upgrade::upgrade;
use hyper::{Request, Body, Response};

async fn server_upgrade(
  mut req: Request<Body>,
) -> Result<Response<Body>, Box<dyn std::error::Error + Send + Sync>> {
  let (response, fut) = upgrade::upgrade(&mut req)?;

  tokio::spawn(async move {
    if let Err(e) = handle_client(fut).await {
      eprintln!("Error in websocket connection: {}", e);
    }
  });

  Ok(response)
}

使用 handshake 模块进行客户端握手:

use fastwebsockets::handshake;
use fastwebsockets::WebSocket;
use hyper::{Request, Body, upgrade::Upgraded, header::{UPGRADE, CONNECTION}};
use tokio::net::TcpStream;
use std::future::Future;

// Define a type alias for convenience
type Result<T> =
  std::result::Result<T, Box<dyn std::error::Error + Send + Sync>>;

async fn connect() -> Result<WebSocket<Upgraded>> {
  let stream = TcpStream::connect("localhost:9001").await?;

  let req = Request::builder()
    .method("GET")
    .uri("http://localhost:9001/")
    .header("Host", "localhost:9001")
    .header(UPGRADE, "websocket")
    .header(CONNECTION, "upgrade")
    .header(
      "Sec-WebSocket-Key",
      fastwebsockets:🤝:generate_key(),
    )
    .header("Sec-WebSocket-Version", "13")
    .body(Body::empty())?;

  let (ws, _) = handshake::client(&SpawnExecutor, req, stream).await?;
  Ok(ws)
}

// Tie hyper's executor to tokio runtime
struct SpawnExecutor;

impl<Fut> hyper::rt::Executor<Fut> for SpawnExecutor
where
  Fut: Future + Send + 'static,
  Fut::Output: Send + 'static,
{
  fn execute(&self, fut: Fut) {
    tokio::task::spawn(fut);
  }
}
  • 通过 Autobahn|TestSuite1 并使用 LLVM 的 libfuzzer 进行模糊测试

(文/开源中国)    




评论 (0)
游客请输入验证码
最新评论
0
0
收藏