Следите за новинками
в нашем Telegram канале. Жми, чтобы подписаться:)
⊗rsSpWsEx 272 of 288 menu
◀ ▶

Обмен WebSocket-сообщениями в Rust

После перехода стороны обмениваются кадрами в обе стороны. Клиент шлет короткий текст, сервер читает его в цикле и может сразу записать ответ в тот же сокет.

На сервере при текстовом кадре hello отправим ответ hi:

use axum::{ extract::ws::{Message, WebSocket, WebSocketUpgrade}, response::IntoResponse, routing::get, Router, }; #[tokio::main] async fn main() { let app = Router::new().route("/", get(ws_entry)); let listener = match tokio::net::TcpListener::bind("127.0.0.1:3000").await { Ok(l) => l, Err(e) => { eprintln!("{}", e); return; } }; match axum::serve(listener, app).await { Ok(()) => {} Err(e) => eprintln!("{}", e), } } async fn ws_entry(ws: WebSocketUpgrade) -> impl IntoResponse { ws.on_upgrade(handle_socket) } async fn handle_socket(mut socket: WebSocket) { loop { let msg = match socket.recv().await { Ok(Some(m)) => m, Ok(None) => break, Err(e) => { eprintln!("{}", e); break; } }; match msg { Message::Text(text) if text == "hello" => { match socket.send(Message::Text("hi".into())).await { Ok(()) => println!("replied"), Err(e) => { eprintln!("{}", e); break; } } } Message::Text(text) => { println!("skip {}", text); } Message::Close(_) => break, _ => {} } } }

Запись ответа тоже возвращает результат. Сбой отправки выходим из цикла, чтобы не читать из уже мертвого канала.

Клиент шлет hello и ждет текст в ответ:

use futures_util::{SinkExt, StreamExt}; use tokio_tungstenite::{connect_async, tungstenite::Message}; #[tokio::main] async fn main() { let url = "ws://127.0.0.1:3000"; let (stream, _response) = match connect_async(url).await { Ok(pair) => pair, Err(e) => { eprintln!("{}", e); return; } }; let (mut write, mut read) = stream.split(); match write.send(Message::Text("hello".into())).await { Ok(()) => {} Err(e) => { eprintln!("{}", e); return; } } match read.next().await { Some(Ok(Message::Text(text))) => println!("answer {}", text), Some(Ok(_)) => println!("unexpected"), Some(Err(e)) => eprintln!("{}", e), None => println!("closed"), } }

Дан текст запроса:

let text = "hello";

На сервере при таком кадре отправьте hi и выведите done после успешной записи.

Дан текст запроса:

let text = "hello";

На клиенте отправьте его, прочитайте один кадр и напечатайте строку hi при варианте текста.

Скажите, почему ответ на сервере удобно писать сразу после чтения в том же асинхронном блоке.

← →
↑
Мы используем cookie для работы сайта, аналитики и персонализации. Обработка данных происходит согласно Политике конфиденциальности.
принять все настроить отклонить