.NET C#控制台实现事件驱动WebSocket(Stream Deck插件开发)
实现C#控制台程序的Elgato Stream Deck事件驱动WebSocket插件
可行方案:基于System.Net.WebSockets.ClientWebSocket实现事件驱动模型
System.Net.WebSockets.ClientWebSocket完全可以在C#控制台程序中使用,虽然它本身提供的是异步API而非原生事件驱动模型,但我们可以基于它封装出符合需求的事件触发逻辑,模拟Open、Message、Close、Error等事件。
核心实现思路
- 封装一个WebSocket客户端类,内部维护
ClientWebSocket实例,通过异步循环监听消息,在对应阶段触发自定义事件。 - 定义对应场景的事件委托,覆盖连接建立、消息接收、连接关闭、错误触发四种核心场景。
- 在连接成功后触发Open事件执行Stream Deck注册逻辑;收到消息时触发Message事件解析设备上报内容;连接关闭或出错时触发对应事件。
示例代码实现
using System; using System.Net.WebSockets; using System.Text; using System.Threading; using System.Threading.Tasks; public class StreamDeckWebSocketClient { // 定义事件委托 public event Action OnOpen; public event Action<string> OnMessage; public event Action<WebSocketCloseStatus?, string> OnClose; public event Action<Exception> OnError; private ClientWebSocket _webSocket; private CancellationTokenSource _cts; public async Task ConnectAsync(Uri uri) { _webSocket = new ClientWebSocket(); _cts = new CancellationTokenSource(); try { await _webSocket.ConnectAsync(uri, _cts.Token); // 触发连接建立事件 OnOpen?.Invoke(); // 启动消息监听循环 await ListenForMessagesAsync(); } catch (Exception ex) { OnError?.Invoke(ex); } finally { await CloseAsync(); } } private async Task ListenForMessagesAsync() { var buffer = new byte[1024 * 4]; while (_webSocket.State == WebSocketState.Open) { try { var result = await _webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), _cts.Token); if (result.MessageType == WebSocketMessageType.Close) { await _webSocket.CloseAsync(result.CloseStatus.Value, result.CloseStatusDescription, _cts.Token); OnClose?.Invoke(result.CloseStatus, result.CloseStatusDescription); break; } var message = Encoding.UTF8.GetString(buffer, 0, result.Count); // 触发消息接收事件 OnMessage?.Invoke(message); } catch (Exception ex) { OnError?.Invoke(ex); break; } } } public async Task SendMessageAsync(string message) { if (_webSocket.State != WebSocketState.Open) throw new InvalidOperationException("WebSocket连接未建立"); var buffer = Encoding.UTF8.GetBytes(message); await _webSocket.SendAsync(new ArraySegment<byte>(buffer), WebSocketMessageType.Text, true, _cts.Token); } public async Task CloseAsync() { if (_webSocket.State == WebSocketState.Open) { await _webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "客户端主动关闭", CancellationToken.None); } _cts?.Cancel(); _webSocket?.Dispose(); _cts?.Dispose(); } }
使用示例
class Program { static async Task Main(string[] args) { var wsClient = new StreamDeckWebSocketClient(); // 绑定事件处理逻辑 wsClient.OnOpen += () => { Console.WriteLine("WebSocket连接已建立,执行Stream Deck注册..."); // 在这里发送Stream Deck要求的注册消息 // await wsClient.SendMessageAsync("{\"event\": \"register\", \"uuid\": \"你的插件UUID\"}"); }; wsClient.OnMessage += (message) => { Console.WriteLine($"收到设备消息:{message}"); // 按照Stream Deck API规范解析消息,处理对应事件 }; wsClient.OnClose += (status, description) => { Console.WriteLine($"连接关闭:{status} - {description}"); }; wsClient.OnError += (ex) => { Console.WriteLine($"连接出错:{ex.Message}"); }; // 替换为Stream Deck的实际WebSocket地址 var streamDeckUri = new Uri("ws://localhost:2356"); await wsClient.ConnectAsync(streamDeckUri); // 保持控制台程序运行 Console.ReadLine(); await wsClient.CloseAsync(); } }
关键说明
ClientWebSocket是.NET标准库组件,支持所有.NET平台(包括.NET Core/.NET 5+),完全适配控制台程序场景。- 上述封装通过异步监听循环,将原生异步API转换为事件驱动模式,完全匹配你需要的Open/Message事件触发需求。
- 注册逻辑和消息解析可直接对接Elgato Stream Deck的官方API规范,将JSON消息反序列化为实体类处理即可。
内容的提问来源于stack exchange,提问作者Michael Kintscher they-them
相关产品推荐
相关产品推荐

