Сервер WebSocket в Rust
Серверная часть начинается с таблицы маршрутов того же крейта, что уже слушал HTTP-запросы. Для перехода нужна функция с ws, которая возвращает ответ согласия и передает сокет в асинхронный блок.
В проект с приемом добавьте возможность вебсокета у крейта маршрутизации:
cargo add axum --features ws
cargo add tokio --features macros,rt-multi-thread
Свяжем корневой адрес с обработчиком перехода и циклом чтения кадров:
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) => {
println!("text {}", text);
}
Message::Close(_) => break,
_ => {}
}
}
}
Каждый успешный прием возвращает вариант кадра. Текст выводим на экран, кадр закрытия завершает цикл, пустой результат чтения тоже выходит из цикла.
Тот же цикл можно сузить до одного текстового кадра перед выходом:
async fn handle_socket(mut socket: WebSocket) {
loop {
let msg = match socket.recv().await {
Ok(Some(m)) => m,
Ok(None) => break,
Err(_) => break,
};
if let Message::Text(text) = msg {
println!("once {}", text);
break;
}
if matches!(msg, Message::Close(_)) {
break;
}
}
}
Дан текст кадра:
let text = "ping";
В цикле чтения выведите этот текст
на экран при варианте Text
и выйдите из цикла после первого
такого кадра.
Скажите, чем пустой результат чтения отличается от кадра закрытия для выхода из цикла.
Дан порт:
let port = 3000;
Привяжите прием к 127.0.0.1
и этому порту и опишите, куда
попадает сбой привязки при разборе
через сопоставление.