WebSocket应用

概述

WebSocket是一种在单个TCP连接上进行全双工通信的协议。Silent框架提供了完整的WebSocket支持,让您能够轻松构建实时通信应用。

基本用法

创建WebSocket处理器

use silent::{handler::WebSocketHandler, response::WebSocket};

#[derive(Default)]
pub struct MyWebSocketHandler;

#[async_trait::async_trait]
impl WebSocketHandler for MyWebSocketHandler {
    async fn on_connect(&self, ws: WebSocket) {
        // 处理新的WebSocket连接
    }

    async fn on_message(&self, ws: WebSocket, msg: String) {
        // 处理接收到的消息
    }

    async fn on_close(&self, ws: WebSocket) {
        // 处理连接关闭
    }
}

注册WebSocket路由

use silent::prelude::*;

async fn create_app() -> Router {
    let app = Router::new();
    app.at("/ws").ws(MyWebSocketHandler::default())
}

实战示例:聊天室应用

Silent框架的examples目录提供了一个完整的WebSocket聊天室示例。以下是实现要点:

1. 管理连接状态

使用共享状态管理活跃的WebSocket连接:

use std::sync::Arc;
use tokio::sync::RwLock;

type Connections = Arc<RwLock<HashMap<String, WebSocket>>>;

#[derive(Clone)]
struct ChatHandler {
    connections: Connections,
}

2. 广播消息

impl ChatHandler {
    async fn broadcast(&self, message: &str, sender: &str) {
        let connections = self.connections.read().await;
        for (id, ws) in connections.iter() {
            if id != sender {
                ws.send(message.to_string()).await;
            }
        }
    }
}

3. 错误处理

妥善处理WebSocket连接的错误情况:

async fn handle_error(ws: WebSocket, error: Error) {
    log::error!("WebSocket error: {}", error);
    ws.close().await;
}

性能优化建议

  1. 连接管理

    • 及时清理断开的连接

    • 使用连接池限制最大连接数

  2. 消息处理

    • 对大消息进行分片处理

    • 实现消息压缩

  3. 并发处理

    • 使用异步任务处理耗时操作

    • 避免长时间占用锁

安全建议

  1. 认证授权

    • 实现WebSocket连接的身份验证

    • 控制消息访问权限

  2. 输入验证

    • 验证消息格式和大小

    • 防止恶意数据注入

  3. 限流保护

    • 实现连接频率限制

    • 控制消息发送速率

调试与监控

  1. 日志记录

    • 记录连接生命周期事件

    • 跟踪关键业务消息

  2. 性能指标

    • 监控连接数量

    • 跟踪消息处理延迟

常见问题解决

  1. 连接断开处理

    • 实现重连机制

    • 保存未发送的消息

  2. 心跳检测

    • 定期发送ping消息

    • 处理超时连接

参考示例

完整的示例代码可以在Silent框架的examples目录中找到:

  • examples/websocket - 基本的WebSocket示例

  • examples/websocket-chat - 完整的聊天室应用示例

Last updated

Was this helpful?