C# Net Core 使用 ClientWebSocket 实现 WebSocket 客户端
2023-09-11 14:14:05 时间
C# 使用 ClientWebSocket 实现 WebSocket 客户端
C# Net Core 使用 ClientWebSocket 实现 WebSocket 客户端
Net Core 使用 ClientWebSocket 实现 WebSocket 客户端
我们模仿HTML5的实现方式来重写一个C#类
https://www.runoob.com/html/html5-websocket.html
WebSocket 属性
HTML5 | 描述 | NET Core | 描述 |
readyState |
只读属性 readyState 表示连接状态,可以是以下值: 0 - 表示连接尚未建立。 1 - 表示连接已建立,可以进行通信。 2 - 表示连接正在进行关闭。 3 - 表示连接已经关闭或者连接不能打开。 |
State | WebSocket状态(点击看官方文档) |
bufferedAmount | 只读属性 bufferedAmount 已被 send() 放入正在队列中等待传输,但是还没有发出的 UTF-8 文本字节数。 | ------ | 无此属性 |
WebSocket 事件
HTML5 | 描述 | NET Core | 描述 |
onopen | 连接建立时触发 | OnOpen | 连接建立时触发 |
onmessage | 客户端接收服务端数据时触发 | OnMessage | 客户端接收服务端数据时触发(暂时只支持文本消息) |
onerror | 通信发生错误时触发 | OnError |
通信发生错误时触发 (如果处理消息中有错误事件没有处理,这里也会抛出并断开链接) |
onclose | 连接关闭时触发 | OnClose | 连接关闭时触发 |
WebSocket 方法
HTML5 | 描述 | NET Core | 描述 |
send() | 使用连接发送数据 | bool Send(string mess) bool Send(byte[] bytes) |
使用连接发送文本消息 返回:是否尝试了发送 |
close() | 关闭连接 |
void Close() void Close(WebSocketCloseStatus closeStatus, string statusDescription) |
关闭连接(关闭原因为用户手动关闭) 关闭连接(自定义关闭原因) |
代码如下:
创建文件WSocketClientHelp.cs:
复制如下代码进去
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
|
using System; using System.Collections.Generic; using System.Linq; using System.Net.WebSockets; using System.Text; using System.Threading; using System.Threading.Tasks; namespace YingCaiEdu.Common.HttpHelp { public class WSocketClientHelp { ClientWebSocket ws = null ; Uri uri = null ; bool isUserClose = false ; //是否最后由用户手动关闭 /// <summary> /// WebSocket状态 /// </summary> public WebSocketState? State { get => ws?.State; } /// <summary> /// 包含一个数据的事件 /// </summary> public delegate void MessageEventHandler( object sender, string data); public delegate void ErrorEventHandler( object sender, Exception ex); /// <summary> /// 连接建立时触发 /// </summary> public event EventHandler OnOpen; /// <summary> /// 客户端接收服务端数据时触发 /// </summary> public event MessageEventHandler OnMessage; /// <summary> /// 通信发生错误时触发 /// </summary> public event ErrorEventHandler OnError; /// <summary> /// 连接关闭时触发 /// </summary> public event EventHandler OnClose; public WSocketClientHelp( string wsUrl) { uri = new Uri(wsUrl); ws = new ClientWebSocket(); } /// <summary> /// 打开链接 /// </summary> public void Open() { Task.Run(async () => { if (ws.State == WebSocketState.Connecting || ws.State == WebSocketState.Open) return ; string netErr = string .Empty; try { //初始化链接 isUserClose = false ; ws = new ClientWebSocket(); await ws.ConnectAsync(uri, CancellationToken.None); if (OnOpen != null ) OnOpen(ws, new EventArgs()); Send( "放映" ); //全部消息容器 List< byte > bs = new List< byte >(); //缓冲区 var buffer = new byte [1024 * 4]; //监听Socket信息 WebSocketReceiveResult result = await ws.ReceiveAsync( new ArraySegment< byte >(buffer), CancellationToken.None); //是否关闭 while (!result.CloseStatus.HasValue) { //文本消息 if (result.MessageType == WebSocketMessageType.Text) { bs.AddRange(buffer.Take(result.Count)); //消息是否已接收完全 if (result.EndOfMessage) { //发送过来的消息 string userMsg = Encoding.UTF8.GetString(bs.ToArray(), 0, bs.Count); if (OnMessage != null ) OnMessage(ws, userMsg); //清空消息容器 bs = new List< byte >(); } } //继续监听Socket信息 result = await ws.ReceiveAsync( new ArraySegment< byte >(buffer), CancellationToken.None); } ////关闭WebSocket(服务端发起) //await ws.CloseAsync(result.CloseStatus.Value, result.CloseStatusDescription, CancellationToken.None); } catch (Exception ex) { netErr = " .Net发生错误" + ex.Message; if (OnError != null ) OnError(ws, ex); //if (ws != null && ws.State == WebSocketState.Open) // //关闭WebSocket(客户端发起) // await ws.CloseAsync(WebSocketCloseStatus.Empty, ex.Message, CancellationToken.None); } finally { if (!isUserClose) Close(ws.CloseStatus.Value, ws.CloseStatusDescription + netErr); } }); } /// <summary> /// 使用连接发送文本消息 /// </summary> /// <param name="ws"></param> /// <param name="mess"></param> /// <returns>是否尝试了发送</returns> public bool Send( string mess) { if (ws.State != WebSocketState.Open) return false ; Task.Run(async () => { var replyMess = Encoding.UTF8.GetBytes(mess); //发送消息 await ws.SendAsync( new ArraySegment< byte >(replyMess), WebSocketMessageType.Text, true , CancellationToken.None); }); return true ; } /// <summary> /// 使用连接发送字节消息 /// </summary> /// <param name="ws"></param> /// <param name="mess"></param> /// <returns>是否尝试了发送</returns> public bool Send( byte [] bytes) { if (ws.State != WebSocketState.Open) return false ; Task.Run(async () => { //发送消息 await ws.SendAsync( new ArraySegment< byte >(bytes), WebSocketMessageType.Binary, true , CancellationToken.None); }); return true ; } /// <summary> /// 关闭连接 /// </summary> public void Close() { isUserClose = true ; Close(WebSocketCloseStatus.NormalClosure, "用户手动关闭" ); } public void Close(WebSocketCloseStatus closeStatus, string statusDescription) { Task.Run(async () => { try { //关闭WebSocket(客户端发起) await ws.CloseAsync(closeStatus, statusDescription, CancellationToken.None); } catch (Exception ex) { } ws.Abort(); ws.Dispose(); if (OnClose != null ) OnClose(ws, new EventArgs()); }); } } } |
使用方法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
|
using System; using System.Collections.Generic; using System.Linq; using System.Net.WebSockets; using System.Text; using System.Threading; using System.Threading.Tasks; using YingCaiEdu.Common.HttpHelp; namespace YingCaiEdu.PPT.VstoPpt { public class PptSocket { private static PptSocket _this; public static PptSocket This { get { if (_this == null ) { _this = new PptSocket(); } return _this; } } public WSocketClientHelp wSocketClient = new WSocketClientHelp( "wss://baidu.com?user=ppt" ); public void Go() { wSocketClient.OnOpen -= WSocketClient_OnOpen; wSocketClient.OnMessage -= WSocketClient_OnMessage; wSocketClient.OnClose -= WSocketClient_OnClose; wSocketClient.OnError -= WSocketClient_OnError; wSocketClient.OnOpen += WSocketClient_OnOpen; wSocketClient.OnMessage += WSocketClient_OnMessage; wSocketClient.OnClose += WSocketClient_OnClose; wSocketClient.OnError += WSocketClient_OnError; wSocketClient.Open(); } private void WSocketClient_OnError( object sender, Exception ex) { } private void WSocketClient_OnClose( object sender, EventArgs e) { } private void WSocketClient_OnMessage( object sender, string data) { //处理的消息错误将会忽略 try { if (data.Contains( "放映" )) { PptVstoApp.GetPptApp.SlideShowFromCurrent(); } } catch (Exception ex) { } } private void WSocketClient_OnOpen( object sender, EventArgs e) { } } } |
完成
转自:https://www.cnblogs.com/ping9719/p/14821508.html
相关文章
- RabbitMQ .NET/C# Client API Guide
- ASP.NET Razor - C# and VB Code Syntax
- 代码走查25条疑问 C# 跳转新的标签页 C#线程处理 .Net 特性 attribute 学习 ----自定义特性 看懂 ,学会 .NET 事件的正确姿势-简单版
- MVC+Spring.NET+NHibernate .NET SSH框架整合 C# 委托异步 和 async /await 两种实现的异步 如何消除点击按钮时周围出现的白线? Linq中 AsQueryable(), AsEnumerable()和ToList()的区别和用法
- ExpandoObject与DynamicObject的使用 RabbitMQ与.net core(一)安装 RabbitMQ与.net core(二)Producer与Exchange ASP.NET Core 2.1 : 十五.图解路由(2.1 or earler) .NET Core中的一个接口多种实现的依赖注入与动态选择看这篇就够了
- C# 动态创建SQL数据库(二) 在.net core web项目中生成二维码 后台Post/Get 请求接口 方式 WebForm 页面ajax 请求后台页面 方法 实现输入框小数多 自动进位展示,编辑时实际值不变 快速掌握Gif动态图实现代码 C#处理和对接HTTP接口请求
- 采用异步来实现重新连接服务器或者重新启动服务 C#中类的属性的获取 SignalR2简易数据看板演示 C#动态调用泛型类、泛型方法 asp .net core Get raw request. 从壹开始前后端分离[.NetCore 不定期更新] 38 ║自动初始化数据库
- .NET Core实战项目之CMS 第二章 入门篇-快速入门ASP.NET Core看这篇就够了 [WPF]为旧版本的应用添加触控支持 js css等静态文件版本控制,一处配置多处更新.net版【原创】 C#图片处理,缩略图制作 SqlDataReader 结果集 转成 DataTable DataTable转成List集合 如何使用linq读取DataTable集合?
- .net mvc 站点自带简易SSL加密传输 Word报告自动生成(例如 导出数据库结构) 微信小程序:动画(Animation) SignalR 设计理念(一) ASP.NET -- WebForm -- ViewState ASP.NET -- 一般处理程序ashx 常用到的一些js方法,记录一下 CryptoJS与C#AES加解密互转
- 项目开发中的一些注意事项以及技巧总结 基于Repository模式设计项目架构—你可以参考的项目架构设计 Asp.Net Core中使用RSA加密 EF Core中的多对多映射如何实现? asp.net core下的如何给网站做安全设置 获取服务端https证书 Js异常捕获
- ASP.NET MVC Filters 4种默认过滤器的使用【附示例】 数据库常见死锁原因及处理 .NET源码中的链表 多线程下C#如何保证线程安全? .net实现支付宝在线支付 彻头彻尾理解单例模式与多线程 App.Config详解及读写操作 判断客户端是iOS还是Android,判断是不是在微信浏览器打开
- 线程安全使用(四) [.NET] 简单接入微信公众号开发:实现自动回复 [C#]C#中字符串的操作 自行实现比dotcore/dotnet更方便更高性能的对象二进制序列化 自已动手做高性能消息队列 自行实现高性能MVC WebAPI 面试题随笔 字符串反转
- Visual Studio 2017中使用正则修改部分内容 如何使用ILAsm与ILDasm修改.Net exe(dll)文件 C#学习-图解教程(1):格式化数字字符串 小程序开发之图片转Base64(C#、.Net) jquery遍历table为每一个单元格取值及赋值 。net加密解密相关方法 .net关于坐标之间一些简单操作
- 如何在Visual Studio 2017中使用C# 7+语法 构建NetCore应用框架之实战篇(二):BitAdminCore框架定位及架构 构建NetCore应用框架之实战篇系列 构建NetCore应用框架之实战篇(一):什么是框架,如何设计一个框架 NetCore入门篇:(十二)在IIS中部署Net Core程序
- 路由其实也可以很简单-------Asp.net WebAPI学习笔记(一) ASP.NET WebApi技术从入门到实战演练 C#面向服务WebService从入门到精通 DataTable与List<T>相互转换
- Word控件Spire.Doc 【图像形状】教程(3) :在 C#/VB.NET 中的指定位置插入图像
- Word控件Spire.Doc 【文本】教程(19) ;如何在 C#、VB.NET 中通过 Word 中的正则表达式查找和替换文本
- ROS#资讯汇总(ROS、C#、.NET和Unity3D)
- 二、Core授权-2 之.net core 基于Identity 授权
- 一、Core授权-2 之.net core 基于Jwt实现Token令牌
- c# 连接mysql配置config,不用装net connector
- 浅谈C#.NET防止SQL注入式攻击