You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Kotlin的WebSocketSession在C#中的等效对象及实现验证

问题分析与解答

你当前的C# initSession方法仅完成了WebSocket对象的实例化,和Kotlin中initSession的功能并不完全等效——Kotlin的client.webSocketSession是挂起函数,会主动发起WebSocket连接并等待连接建立完成后才返回,而你的代码只是创建了对象,没有触发实际的连接动作。

关键差异与修正方向

  1. 连接建立:需要在实例化WebSocket后,主动调用连接方法(对应Kotlin中webSocketSession的连接逻辑)。
  2. 异步处理:C#的WebSocket操作都是异步的,建议用async/await模式,和Kotlin的挂起函数行为对齐。
  3. 完整功能对应:需要补充send、消息监听、closeSession的实现,才能和你Kotlin中的WebSocketServiceImpl功能完全匹配。

等效的C#实现示例

假设使用.NET标准库中的ClientWebSocket(C#官方推荐的WebSocket客户端实现),完整实现如下:

using System.Net.WebSockets;
using System.Text;
using System.Text.Json;

public class WebSocketServiceImpl
{
    private ClientWebSocket? _socket;

    // 对应Kotlin的initSession,异步发起连接
    public async Task InitSession(string username)
    {
        _socket = new ClientWebSocket();
        // 连接到指定WebSocket地址,带username参数
        var uri = new Uri($"ws://xxx.xxx.xxx.xxx:xxxx/myRoute?username={username}");
        await _socket.ConnectAsync(uri, CancellationToken.None);
        // 连接成功后启动消息监听任务
        _ = ListenForMessages();
    }

    // 对应Kotlin的send方法,序列化对象并发送文本帧
    public async Task Send(MyObj myObj)
    {
        if (_socket?.State != WebSocketState.Open) return;
        
        try
        {
            var json = JsonSerializer.Serialize(myObj);
            var buffer = Encoding.UTF8.GetBytes(json);
            await _socket.SendAsync(
                new ArraySegment<byte>(buffer), 
                WebSocketMessageType.Text, 
                endOfMessage: true, 
                CancellationToken.None);
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.ToString());
        }
    }

    // 对应Kotlin的observePrintableMessages,监听并解析消息
    private async Task ListenForMessages()
    {
        if (_socket == null) return;
        
        var buffer = new byte[1024 * 4];
        try
        {
            while (_socket.State == WebSocketState.Open)
            {
                var result = await _socket.ReceiveAsync(
                    new ArraySegment<byte>(buffer), 
                    CancellationToken.None);
                
                if (result.MessageType == WebSocketMessageType.Text)
                {
                    var json = Encoding.UTF8.GetString(buffer, 0, result.Count);
                    var myObj = JsonSerializer.Deserialize<MyObj>(json);
                    // 通过事件对外暴露接收的消息(替代Kotlin的Flow)
                    OnMessageReceived?.Invoke(myObj);
                }
                else if (result.MessageType == WebSocketMessageType.Close)
                {
                    await _socket.CloseAsync(
                        WebSocketCloseStatus.NormalClosure, 
                        "Closing", 
                        CancellationToken.None);
                }
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.ToString());
        }
    }

    // 对应Kotlin的closeSession,关闭连接
    public async Task CloseSession()
    {
        if (_socket?.State == WebSocketState.Open)
        {
            await _socket.CloseAsync(
                WebSocketCloseStatus.NormalClosure, 
                "Client closed session", 
                CancellationToken.None);
        }
        _socket?.Dispose();
        _socket = null;
    }

    // 用于对外暴露接收的消息
    public event Action<MyObj>? OnMessageReceived;
}

// 与Kotlin端结构一致的MyObj类
public class MyObj
{
    // 示例属性,根据实际需求调整
    public string? Content { get; set; }
    public string? Sender { get; set; }
}

补充说明

  • 如果你的C#环境是Unity或其他特殊平台,可能需要使用对应平台的WebSocket实现(比如Unity的WebSocket类),但核心逻辑一致:实例化对象→发起连接→发送消息→监听消息→关闭连接。
  • 你最初的代码中协议参数传了空字符串,只要Ktor服务器没有要求特定的子协议,这个是没问题的;如果服务器有指定,需要在实例化WebSocket时传入对应协议名称。

内容的提问来源于stack exchange,提问作者AccountForWorks

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 20:15:42