IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 网络协议 -> 最新 .NET Core 中 SignalR的使用 以及 WebSocket的使用 同时在Asp.Net MVC 中 WebSocket的使用 -> 正文阅读

[网络协议]最新 .NET Core 中 SignalR的使用 以及 WebSocket的使用 同时在Asp.Net MVC 中 WebSocket的使用

ASP.NET MVC 中使用WebSocket 笔记

1.采用控制器的方法 这个只写建立链接的方法的核心方法

1.1 踩坑 网上都是直接 传个异步方法 直接接受链接 自己尝试了好多次链接是打开的,到时获取不到链接里面的内容!! (如果是我理解有问题的话,欢迎讨论,毕竟这个问题卡了我好久!)

1.2 自己建立链接的使用截图?方法

? ?

/// <summary>
        /// WebSocket链接 demo地址 ws://Localhost:8080/Get
        /// </summary>
        [HttpGet]
        public void Get()
        {
            if (System.Web.HttpContext.Current.IsWebSocketRequest)
            {
                //System.Web.HttpContext.Current.AcceptWebSocketRequest(AnalysisOptionChat);
                System.Web.HttpContext.Current.AcceptWebSocketRequest(async (context) => await AnalysisOptionChat(context));
            }
        }
 

1.3?判断是WebSocket?链接后?处理消息

 1 
/// <summary>
        /// WebSocket链接操作
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        private async Task AnalysisOptionChat(AspNetWebSocketContext context)
        {
            var webSocket = context.WebSocket;
            #region 测试demo
            try
            {
                ConsoleWrite.ConsoleInfo($"Websocket client add--> 自己需要实现 保存链接");
                WebSocketReceiveResult clientData = null;
                do
                {
                    var buffer = new ArraySegment<byte>(new byte[1024 * 1000]);
                    //if (clientData.MessageType == WebSocketMessageType.Text && !clientData.CloseStatus.HasValue)
                    if (webSocket.State == WebSocketState.Open && clientData.MessageType == WebSocketMessageType.Text)
                    {
                        string msgString = Encoding.UTF8.GetString(buffer.Array, 0, clientData.Count);
                        var sendData = string.Empty;
                        if ("rub".Equals(msgString))//心跳
                        {

                        }
                        else
                        {
                            int size = clientData.Count;

                            #region 通知
                            #endregion

                            #region DB持久化 操作
                            #endregion
                        }
                    }
                }
                //while (!clientData.CloseStatus.HasValue);
                while (webSocket.State == WebSocketState.Open);

                var state = webSocket.State;
                ConsoleWrite.ConsoleWarning($"Websocket client closed1-->{state.ToString()}");
                ConsoleWrite.ConsoleWarning($"Websocket client closed2-->{clientData.CloseStatus.Value}");
                //关闭事件
                await webSocket.CloseAsync(clientData.CloseStatus.Value, clientData.CloseStatusDescription, CancellationToken.None);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }

            #endregion
}

1.4?在Asp.Net MVC?中使用可能会遇到?跨域的问题?一下是解决方案

 1 
<system.webServer>
    <!--全局跨域-->
    <httpProtocol>
      <customHeaders>
        <add name="Access-Control-Allow-Origin" value="*" />
        <!--<add name="Access-Control-Allow-Headers" value="*" />
        <add name="Access-Control-Allow-Methods" value="GET,POST,PUT,DELETE,OPTIONS" />-->
      </customHeaders>
    </httpProtocol>
<system.webServer>

.NET?Core?中使用WebSocket 笔记

1.在WepApi中使用法 这个只写建立链接的方法的核心方法

1.首先需要在Startup.cs?里面的?ConfigureServices里面配置跨域?如果不牵扯跨域的话?可以忽略 1,2 (里面的跨域) 跨域详细配置如下

services.AddCors(options =>
            {
                options.AddPolicy("WebSocketCors", builder =>
                {
                    builder.SetIsOriginAllowed(_ => true).AllowAnyMethod().AllowAnyHeader().AllowCredentials();
                });
            });

2.然后在?Configure方法 里面加入管道?

app.UseWebSockets(new Microsoft.AspNetCore.Builder.WebSocketOptions
            {
                //保持活动间隔
                KeepAliveInterval = TimeSpan.FromMinutes(5),
            });

            // 注意这个是重点!!!!
            app.UseMiddleware<WebsocketHandlerMiddleware>();

 //自定义跨域规则
            app.UseCors("WebSocketCors");

详细截图如下

?3.?请求中间件 WebsocketHandlerMiddleware.cs?详细介绍如下

public class WebsocketHandlerMiddleware
    {
        private readonly RequestDelegate _next;

        public WebsocketHandlerMiddleware(RequestDelegate next)
        {
            _next = next;
        }

        public async Task Invoke(HttpContext context)
        {
            if (context.Request.Path == "/ws")
            {
                //客户端与服务器成功建立连接后,服务器会循环异步接收客户端发送的消息,收到消息后就会执行Handle(WebsocketClient websocketClient)中的do{}while;直到客户端断开连接
                //不同的客户端向服务器发送消息后台执行do{}while;时,websocketClient实参是不同的,它与客户端一一对应
                //同一个客户端向服务器多次发送消息后台执行do{}while;时,websocketClient实参是相同的
                if (context.WebSockets.IsWebSocketRequest)
                {
                    var webSocket = await context.WebSockets.AcceptWebSocketAsync();

                }
                else
                {
                    context.Response.StatusCode = 404;
                }
            }
            else
            {
                await _next(context);
            }
        }
    }

里面处理?WebSocket?请求消息的内容?和?1.3? 中方法是一样的?我这里就不重复了?两者的区别都只是?获取方式不一样而已。

.NET?Core?中使用SignalR笔记

1.在WepApi中使用法 这个只写建立链接的方法的核心方法?以及相关方法介绍

所使用的Nuget?包?如下:

1.1?首先需要在Startup.cs?里面的 ConfigureServices方法 注入且配置跨域.

 1
#region SignalR

            services.AddCors(options =>
            {
                options.AddPolicy("SignalRCors", builder =>
                {
                    builder.SetIsOriginAllowed(_ => true).AllowAnyMethod().AllowAnyHeader().AllowCredentials();
                });
            });

            services.AddSignalR().AddHubOptions<SignalrHub>(options =>
            {
                options.EnableDetailedErrors = true;
            })
            // 支持MessagePack
            .AddMessagePackProtocol();

            #endregion

同时还需要?注入加入声明周期?管控?

//特殊的
services.AddSingleton<SignalrHub>();

1.2?在Configure方法里面?的相关使用

//自定义跨域规则
app.UseCors("SignalRCors");

//需要在 Map里面 指定路由
//app.UseHttpsRedirection();
 app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
                //可以设置SignalR相关参数,这里设置地址
                endpoints.MapHub<SignalrHub>("hubs/signalr", options =>
                {
            //配置 几种方式
                    options.Transports = HttpTransportType.WebSockets | HttpTransportType.LongPolling;
                });
            });

1.3?SignalrHub.cs 集线器类的使用介绍?里面有许多用不上的?自己按照需求自己过滤?主要就是?OnConnectedAsync()?建立链接?OnDisconnectedAsync()断开链接?方法的使用!

  1 
//创建SingalR中心跨域
    [EnableCors("SignalRCors")]
    public  class SignalrHub : Hub
    {
        //ReceiveMessage 为客户端监听的 方法名称
        private static string clientSendMethodName = "ReceiveMessage";

        //Redis 存储信息Key
        private static string signalrRedisKey = "SignalRConnections";

        public SignalrHub()
        {

        }


        #region Send

        /// <summary>
        /// 发送消息-指定用户集合发送消息
        /// </summary>
        /// <param name="userIds">通知用户集合</param>
        /// <param name="sendObject">通知OBject</param>
        /// <returns></returns>
        public  async Task SendUserMessage(List<int> userIds,object sendObject)
        {
            //从redis 获取 userIds 对应的 ConnectionId 进行推送
            var connectionUserList = RedisService.GetLPushData<UserConnection>(signalrRedisKey, 0, int.MaxValue);
            if(connectionUserList.Count()<=0) throw new Exception("无连接用户,无法进行消息推送。");
            var sentUserClient = connectionUserList.Where(x => userIds.Contains(x.UserId)).ToList();
            var sendMeaaageToJson = JsonHelper.ObjectToJsonCamelCase(sendObject);

            var connectionIds = sentUserClient.Select(y => y.ConnectionId);

            //全部
            //await Clients.All.SendAsync(clientSendMethodName, new { data = sendMeaaageToJson });

            //指定
            await Clients.Clients(connectionIds).SendAsync(clientSendMethodName, new { data = sendMeaaageToJson });
        }


        //发送消息--发送给所有连接的客户端
        public async Task SendMessage(string msg)
        {
            //await Clients.All.SendAsync(clientSendMethodName, msg);
            Console.WriteLine($"保持心跳链接-->接收参数:{msg}");
        }



        /// <summary>
        /// 除 connectionId 之外的所有发送message
        /// </summary>
        /// <param name="connectionId"></param>
        /// <param name="message"></param>
        /// <returns></returns>
        public Task SendAllExceptMe(string connectionId, string message)
        {

            return Clients.AllExcept(connectionId).SendAsync(clientSendMethodName, $"{Context.ConnectionId}: {message}");
        }

        #endregion



        #region Group分组的话 依据职位 或者 角色来业务循环获取



        #endregion


        #region overrides

        /// <summary>
        /// 当新的客户端连接建立时执行的操作
        /// </summary>
        /// <returns></returns>
        public override async Task OnConnectedAsync()
         {
            //建立者用户Id
            var clientUserId = AuthHelper.GetUserId(Context.User);
            //建立者用户Name
            var clientUserName = Context.User.Identity.Name;
            //建立ConnectionId
            var connectionId = Context.ConnectionId;

            if (clientUserId <= 0 || string.IsNullOrWhiteSpace(clientUserName))
            {
                throw new Exception("建立连接异常,无法获取用户信息。");
            }

            Console.WriteLine($"OnConnectedAsync建立链接----userId:{clientUserId},userName:{clientUserName},connectionId:{ Context.ConnectionId}");

            var userConnections = new List<UserConnection>();
            userConnections.Add(new UserConnection() { UserId = clientUserId, UserName = clientUserName, ConnectionId = connectionId, CreateTime = DateTime.Now });

            //redis存储连接用户信息
            RedisService.SetLPushValue(signalrRedisKey, false, userConnections);

            //获取所有用户的链接信息
            //var aaa = RedisService.GetLPushData<UserConnection>(signalrRedisKey,0,10000000);

            await base.OnConnectedAsync();
        }


        /// <summary>
        /// 当客户端断开连接时执行的操作
        /// </summary>
        /// <param name="exception"></param>
        /// <returns></returns>
        public override async Task OnDisconnectedAsync(Exception exception)
        {
            //建立者用户Id
            var clientUserId = AuthHelper.GetUserId(Context.User);
            //建立者用户Name
            var clientUserName = Context.User.Identity.Name;
            //建立ConnectionId
            var connectionId = Context.ConnectionId;
            //NLogHelper.ActionWarn();

            Console.WriteLine($"OnDisconnectedAsync断开链接----userId:{clientUserId},clientUserName:{clientUserName},connectionId:{ connectionId}");

            var connectionUserList = RedisService.GetLPushData<UserConnection>(signalrRedisKey, 0, int.MaxValue);

            //在redis里面依据 Value 移除
            var removeItem = connectionUserList.Where(x => x.ConnectionId == connectionId).FirstOrDefault();
            if (removeItem != null)
            {
                var Drow = await RedisService.LRemAsync(signalrRedisKey, removeItem);
                //var connectionUserLists = RedisService.GetLPushData<UserConnection>(signalrRedisKey, 0, int.MaxValue);
            }
            await base.OnDisconnectedAsync(exception);
        }

        protected override void Dispose(bool disposing)
        {
            base.Dispose(disposing);
        }

        #endregion


        #region ClearOverTime 清除超时的垃圾数据

        public async Task ClearOverTimeUserRedis(int houre=24)
        {
            var connectionUserList = RedisService.GetLPushData<UserConnection>(signalrRedisKey, 0, int.MaxValue);
            var thisTime = DateTime.Now;
            var delConnection = connectionUserList.Where(x=>(thisTime-x.CreateTime).Duration().TotalHours >= houre).ToList();
            if (delConnection != null)
            {
                foreach (var delItem in delConnection)
                {
                    var Drow = await RedisService.LRemAsync(signalrRedisKey, delItem);
                    //var connectionUserLists = RedisService.GetLPushData<UserConnection>(signalrRedisKey, 0, int.MaxValue);
                }
            }
        }

        #endregion
    }

1.4 SignalrHub.cs?里面所用到的用户链接?UserConnection.cs?类

[Serializable]
    public class UserConnection
    {
        /// <summary>
        /// 用户Id
        /// </summary>
        public int UserId { set; get; }

        /// <summary>
        /// 用户名称
        /// </summary>
        public string UserName { set; get; }

        /// <summary>
        /// 连接Id
        /// </summary>
        public string ConnectionId { set; get; }

        /// <summary>
        /// 创建时间
        /// </summary>
        public DateTime CreateTime { set; get; }
    }

作者声明:

1.文章转载请注明出处 !!!?

2.文章 如有不正确之处欢迎大家讨论,交流,?如果感觉写的还行,或者帮助了您,请点个赞哈,再次谢过~

  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2021-09-02 11:45:12  更:2021-09-02 11:47:15 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 22:53:21-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码