创建WebSocket服务器:TouchSocket框架实践

这里写目录标题

    • 一、概述
    • 二、基本配置
      • 1. 简单创建WebSocket服务
      • 2. 验证连接
      • 3. 基于WebApi创建
    • 三、接收消息
      • 1. 插件订阅
      • 2. 显式调用`ReadAsync`
    • 四、发送消息
      • 1. 发送文本消息
      • 2. 发送二进制消息
      • 3. 发送自定义数据帧
    • 五、关闭连接
    • 六、示例项目

一、概述

WebSocket是一种基于HTTP协议的升级协议,允许客户端与服务器之间进行全双工通信。在TouchSocket框架中,WebSocket功能可以通过HttpService挂载实现,并支持多种插件化扩展。

  • 命名空间TouchSocket.Http.WebSockets
  • 程序集:TouchSocket.Http.dll

二、基本配置

1. 简单创建WebSocket服务

以下代码展示了如何快速创建一个WebSocket服务:

var service = new HttpService();
await service.SetupAsync(new TouchSocketConfig()
    .SetListenIPHosts(7789) // 设置监听端口
    .ConfigurePlugins(a =>
    {
        a.UseWebSocket() // 添加WebSocket功能
            .SetWSUrl("/ws") // 设置连接路径
            .UseAutoPong(); // 自动响应Ping消息
    }));

await service.StartAsync();
service.Logger.Info("服务器已启动");

运行后,客户端可以通过ws://127.0.0.1:7789/ws连接到WebSocket服务。


2. 验证连接

在实际应用中,可能需要对连接请求进行验证。例如,检查URL参数或Header中的Token:

a.UseWebSocket()
    .SetVerifyConnection(VerifyConnection);

private static bool VerifyConnection(IHttpSessionClient client, HttpContext context)
{
    if (!context.Request.IsUpgrade()) return false;

    if (context.Request.UrlEquals("/ws")) return true;

    if (context.Request.UrlEquals("/wsquery"))
    {
        return context.Request.Query.Get("token") == "123456";
    }

    if (context.Request.UrlEquals("/wsheader"))
    {
        return context.Request.Headers.Get("token") == "123456";
    }

    return false;
}

3. 基于WebApi创建

通过WebApi可以更灵活地管理WebSocket连接:

public class MyApiServer : RpcServer
{
    [Router("/connect")]
    [WebApi(Method = HttpMethodType.Get)]
    public async Task ConnectWS(IWebApiCallContext callContext)
    {
        if (callContext.Caller is HttpSessionClient sessionClient)
        {
            if (await sessionClient.SwitchProtocolToWebSocketAsync(callContext.HttpContext))
            {
                sessionClient.WebSocket.AllowAsyncRead = true;
                while (true)
                {
                    using (var result = await sessionClient.WebSocket.ReadAsync())
                    {
                        if (result.IsCompleted) break;
                        Console.WriteLine($"Received: {result.DataFrame.ToText()}");
                    }
                }
            }
        }
    }
}

三、接收消息

WebSocket服务器可以通过两种方式接收消息:插件订阅或显式调用ReadAsync

1. 插件订阅

定义一个插件来处理WebSocket消息:

public class MyWebSocketPlugin : PluginBase, IWebSocketReceivedPlugin
{
    public async Task OnWebSocketReceived(IWebSocket client, WSDataFrameEventArgs e)
    {
        switch (e.DataFrame.Opcode)
        {
            case WSDataType.Text:
                Console.WriteLine(e.DataFrame.ToText());
                await client.SendAsync("Message received!");
                break;
        }
    }
}

使用时注册该插件:

a.Add<MyWebSocketPlugin>();

2. 显式调用ReadAsync

通过IWebSocketHandshakedPlugin插件,在握手成功后直接读取消息:

public class MyReadWebSocketPlugin : PluginBase, IWebSocketHandshakedPlugin
{
    public async Task OnWebSocketHandshaked(IWebSocket client, HttpContextEventArgs e)
    {
        client.AllowAsyncRead = true;

        while (true)
        {
            using (var result = await client.ReadAsync())
            {
                if (result.IsCompleted) break;
                Console.WriteLine($"Received: {result.DataFrame.ToText()}");
            }
        }
    }
}

四、发送消息

1. 发送文本消息

await webSocket.SendAsync("Hello, WebSocket!");

2. 发送二进制消息

await webSocket.SendAsync(new byte[] { 1, 2, 3 });

3. 发送自定义数据帧

using (var frame = new WSDataFrame())
{
    frame.Opcode = WSDataType.Text;
    frame.FIN = true;
    frame.AppendText("Custom Frame");
    await webSocket.SendAsync(frame);
}

五、关闭连接

主动关闭WebSocket连接:

await webSocket.CloseAsync("Closing connection");

或者指定状态码:

await webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "Closing connection");

六、示例项目

  • GitHub仓库:https://github.com/RRQM/TouchSocket
  • Gitee仓库:https://gitee.com/rrqm_Home/touchsocket

通过本文的介绍,您应该能够熟练使用TouchSocket框架创建WebSocket服务器并实现相关功能。希望这些内容对您的开发有所帮助!

你可能感兴趣的:(websocket,服务器,网络协议)