6.14WebSocket 双工通信

WebSocket 是一种在单个 TCP 连接上进行全双工通信的协议。WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在 WebSocket API 中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。

WebSocket 双工通信#

WebSocket 是一种在单个 TCP 连接上进行全双工通信的协议。WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在 WebSocket API 中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。

WebSocket 的应用场景:

  • 实时聊天应用WebSocket 可以实现实时的消息传递,使得用户间的交流几乎无延迟。
  • 在线游戏:对于需要快速响应的游戏,WebSocket 能够提供低延迟的数据传输。
  • 股票市场更新:实时更新股票价格和其他金融信息。
  • 协同编辑工具:允许多个用户同时编辑同一个文档,并实时看到其他人的更改。
  • 实时地图应用:例如导航应用中实时交通状况的更新。

以下示例展示了如何使用 WebSocketClient 连接服务器:

cs
using var webSocketClient = new WebSocketClient("wss://ws.postman-echo.com/raw");    // 支持 ws:// 和 wss://// 连接成功事件webSocketClient.Connected += (sender, s) =>{    Console.WriteLine("连接成功");    return Task.CompletedTask;};// 连接关闭事件webSocketClient.Closed += (sender, args) =>{    Console.WriteLine("连接关闭");    return Task.CompletedTask;};// 接收文本消息webSocketClient.TextReceived += (sender, s) =>{    Console.WriteLine(s.Message);    return Task.CompletedTask;};// 接收二进制消息webSocketClient.BinaryReceived += (sender, s) =>{    Console.WriteLine(s.Message);    return Task.CompletedTask;};// 连接服务器await webSocketClient.ConnectAsync();// 开启一个任务,循环发送消息_ = Task.Run(async () =>{    var i = 0;    while (i < 5)    {        // 发送文本消息        await webSocketClient.SendAsync("Hello, WebSocket!");        await Task.Delay(1000);        i++;    }    // 关闭连接    await webSocketClient.CloseAsync();});// 等待接收消息和关闭事件(阻塞)await webSocketClient.WaitAsync();

WebSocketServer-Sent Events (SSE) 的区别:

  • 通信方向WebSocket 支持全双工双向通信,SSE 仅支持服务器向客户端单向推送数据。
  • 协议WebSocket 使用独立的 WebSocket 协议 (ws://wss://),SSE 基于 HTTP 协议。
  • 握手过程WebSocket 需要特殊的 HTTP 升级头来转换协议,SSE 无需特殊握手,直接通过 HTTP 请求建立连接。
  • 连接保持WebSocket 连接保持直到显式关闭,SSE 可能因网络问题断开,但浏览器会自动重连。
  • 数据格式WebSocket 支持多种数据格式,包括二进制数据,SSE 数据格式较固定,通常是简单的文本消息。
  • 跨域支持WebSocket 建立连接时检查跨域策略,连接后不受限,SSE 依赖于 CORS 策略。

选择使用 WebSocket 还是 SSE 主要取决于具体的应用需求:

  • 如果需要实现双向通信或处理大量数据流,WebSocket 是更好的选择;
  • 如果只是需要服务器向客户端推送更新,且对数据格式要求不高,SSE 可能更加轻量和易于实现。

WebSocketClient 客户端#

框架内置了 WebSocketClient 类型,便于用户通过 wswss 协议与 WebSocket 服务器建立连接。要使用 WebSocket 功能,首先需要创建并初始化 WebSocketClient 的实例。以下详尽列出了 WebSocketClient 实例所具备的全部功能配置选项:

  • 创建 WebSocketClient 客户端

以下是创建 WebSocketClient 实例的三种方式,它们分别通过不同的构造函数重载实现,但实质上最终都调用了带有 WebSocketClientOptions 参数的构造函数来配置连接:

cs
// 直接使用 URL 字符串(支持 ws:// 和 wss://)using var webSocketClient = new WebSocketClient("wss://localhost:7044/ws");// 使用 Uri 对象using var webSocketClient = new WebSocketClient(new Uri("wss://localhost:7044/ws"));// 使用 WebSocketClientOptions 对象进行详细配置using var webSocketClient = new WebSocketClient(new WebSocketClientOptions("wss://localhost:7044/ws"));// 配置内部 ClientWebSocketOptions 实例using var webSocketClient = new WebSocketClient("wss://localhost:7044/ws", options => {});

WebSocketClientOptions 类型包含了多种配置属性,用于定制 ClientWebSocket 连接的详细设置。WebSocketClientOptions,包含以下属性:

  • 属性
    • ServerUri:服务器地址(Uri 类型)。
    • ReconnectInterval:重连的间隔时间(毫秒),默认值为 2 秒。(TimeSpan 类型)。
    • MaxReconnectRetries:最大重连次数,默认 10 次。(int 类型)。
    • Timeout:超时时间(TimeSpan 类型)。
    • ReceiveBufferSize:接收服务器新消息缓冲区大小(以字节为单位的 int 类型)。
    • Configure:用户配置内部 ClientWebSocketOptions 实例(Action<ClientWebSocketOptions> 类型)。

  • WebSocketClient 客户端事件

WebSocketClient 客户端提供了多种事件,允许开发者在 WebSocket 通信的各个阶段插入自定义逻辑。以下示例展示了如何订阅这些事件:

cs
using var webSocketClient = new WebSocketClient("wss://localhost:7044/ws");    // 支持 ws:// 和 wss://// 开始连接时触发事件webSocketClient.Connecting += (s, e) => {};// 连接成功时触发事件webSocketClient.Connected += (s, e) => { };// 开始重新连接时触发事件webSocketClient.Reconnecting += (s, e) => { };// 重新连接成功时触发事件webSocketClient.Reconnected += (s, e) => { };// 开始关闭连接时触发事件webSocketClient.Closing += (s, e) => { };// 关闭连接成功时触发事件webSocketClient.Closed += (s, e) => { };// 开始接收消息时触发事件webSocketClient.ReceivingStarted += (s, e) => { };// 停止接收消息时触发事件webSocketClient.ReceivingStopped += (s, e) => { };// 接收文本消息事件,result 为 WebSocketTextReceiveResult 类型webSocketClient.TextReceived += (s, result) => { };// 接收二进制消息事件,result 为 WebSocketBinaryReceiveResult 类型webSocketClient.BinaryReceived += (s, result) => { };

WebSocketTextReceiveResult 类型派生自 WebSocketReceiveResult ,包含以下属性:

WebSocketBinaryReceiveResult 类型派生自 WebSocketReceiveResult ,包含以下属性:


WebSocketClient 客户端方法

WebSocketClient 类封装了与 WebSocket 服务器进行交互的关键操作,具体包括连接、发送消息和关闭连接三种方法。

cs
using var webSocketClient = new WebSocketClient("wss://localhost:7044/ws");    // 支持 ws:// 和 wss://// 连接服务器await webSocketClient.ConnectAsync(cancellationToken);// 向服务器发送消息await webSocketClient.SendAsync(message, endOfMessage, cancellationToken);  // 发送字符串消息await webSocketClient.SendAsync(byteArray, endOfMessage, cancellationToken);    // 发送二进制消息await webSocketClient.SendAsync(message, webSocketMessageType, endOfMessage, cancellationToken);    // 发送指定类型的消息(文本或二进制)// 等待消息(阻塞)await webSocketClient.WaitAsync(cancellationToken);// 关闭连接await webSocketClient.CloseAsync(cancellationToken);    // 无附加信息关闭await webSocketClient.CloseAsync(closeStatus, closeDescription, cancellationToken); // 提供关闭状态和描述信息关闭