网上看到的一个非常不错的.NET实现的WebSocketClient

网上看到的一个非常不错的.NET实现的WebSocketClient

文件名:WSocketClientHelp

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());
            });
        }

    }

}

使用方法:

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

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注