rust 同一端口实现 websocket 和http
时间: 2023-09-22 20:15:25 浏览: 288
在 Rust 中,可以使用库 `tokio` 来实现在同一端口上同时提供 WebSocket 和 HTTP 服务。
首先,你需要使用 `tokio` 的异步 I/O 功能创建一个 TCP 监听器。然后,你可以使用 `tungstenite` 库来处理 WebSocket 连接,使用 `hyper` 库来处理 HTTP 请求。最后,你可以使用 `async`/`await` 语法编写异步代码来处理客户端的请求和连接。
下面是一个示例代码:
```rust
use std::net::SocketAddr;
use tokio::io::{AsyncReadExt, AsyncWriteExt};
use tokio::net::{TcpListener, TcpStream};
use tokio::sync::mpsc::{unbounded_channel, UnboundedReceiver, UnboundedSender};
use tungstenite::protocol::Message;
use tungstenite::server::accept_async;
use hyper::{Body, Request, Response, Server};
use hyper::service::{make_service_fn, service_fn};
use futures::stream::StreamExt;
async fn handle_websocket_connection(stream: TcpStream) {
let addr = stream.peer_addr().unwrap();
let ws_stream = accept_async(stream).await.unwrap();
println!("New WebSocket connection: {}", addr);
let (ws_sender, mut ws_receiver) = ws_stream.split();
let (tx, rx): (UnboundedSender<Message>, UnboundedReceiver<Message>) = unbounded_channel();
tokio::spawn(async move {
while let Some(message) = rx.next().await {
ws_sender.send(message).await.unwrap();
}
});
while let Some(Ok(message)) = ws_receiver.next().await {
tx.send(message).unwrap();
}
}
async fn handle_http_request(request: Request<Body>) -> Result<Response<Body>, hyper::Error> {
let body = Body::from("Hello, World!");
Ok(Response::new(body))
}
#[tokio::main]
async fn main() {
let addr: SocketAddr = "127.0.0.1:8080".parse().unwrap();
let tcp_listener = TcpListener::bind(&addr).await.unwrap();
let server = Server::builder(tcp_listener);
let make_service = make_service_fn(|_conn| async {
Ok::<_, hyper::Error>(service_fn(handle_http_request))
});
let http_server = server.serve(make_service);
println!("HTTP server listening on {}", addr);
let ws_listener = TcpListener::bind(&addr).await.unwrap();
while let Ok((stream, _)) = ws_listener.accept().await {
tokio::spawn(handle_websocket_connection(stream));
}
}
```
在这个示例代码中,我们首先使用 `TcpListener::bind` 方法创建了一个 TCP 监听器,该监听器绑定在指定的地址和端口上。接下来,我们使用 `Server::builder` 方法创建了一个 HTTP 服务器,并将 TCP 监听器传递给它。然后,我们使用 `make_service_fn` 方法创建了一个服务,该服务将每个 HTTP 请求交给 `handle_http_request` 函数处理。最后,我们使用 `TcpListener::accept` 方法创建了一个无限循环,该循环等待 WebSocket 连接并将它们交给 `handle_websocket_connection` 函数处理。
在 `handle_websocket_connection` 函数中,我们使用 `accept_async` 方法接受 WebSocket 连接,并将其分成读和写两个流。然后,我们使用 `unbounded_channel` 方法创建了一个无界的消息通道,用于在 WebSocket 连接和其他异步任务之间传递消息。我们使用 `tokio::spawn` 方法将一个异步任务添加到运行时中,该任务将从消息通道中读取消息并将其发送到 WebSocket 连接中。最后,我们使用 `next` 方法从 WebSocket 读取器中读取消息,并将其发送到消息通道中。
需要注意的是,在这个示例代码中,WebSocket 和 HTTP 服务共享相同的端口(8080)。这是因为 WebSocket 和 HTTP 协议都基于 TCP 协议,它们可以共享同一个端口。如果你的应用程序需要同时提供多个服务,可以使用不同的路径或子域名来区分它们。
阅读全文