陋室铭
永远也不要停下学习的脚步(大道至简至易)

posts - 2169,comments - 570,views - 413万

 

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

 

posted on   宏宇  阅读(2473)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
历史上的今天:
2019-09-03 sqlserver 创建分区表
2019-09-03 solr的创建分片的方式
2018-09-03 tomcat 内存大小配置
2018-09-03 solr7.1.0学习笔记(10)---Solr发布到Tomcat
2018-09-03 JavaEE进阶——全文检索之Solr7.4服务器
2018-09-03 solr7.4 tomcat环境下搭建(windows)
2018-09-03 solr7.4 安装与使用
< 2025年3月 >
23 24 25 26 27 28 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 1 2 3 4 5

点击右上角即可分享
微信分享提示