zoukankan      html  css  js  c++  java
  • asp.net core+websocket实现实时通信

    1.创建简易通讯协议

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;
    
    namespace Dw.RegApi.Models
    {
        /// <summary>
        /// 通讯协议
        /// </summary>
        public class MsgTemplate
        {
            /// <summary>
            /// 接收人
            /// </summary>
            public string to_id { get; set; }
            /// <summary>
            /// 发送人
            /// </summary>
            public string from_id { get; set; }
            /// <summary>
            /// 发送人昵称
            /// </summary>
            public string from_username { get; set; }
            /// <summary>
            /// 发送人头像
            /// </summary>
            public string from_userpic { get; set; }
            /// <summary>
            /// 发送类型 text,voice等等
            /// </summary>
            public string type { get; set; }
            /// <summary>
            /// 发送内容 
            /// </summary>
            public string data { get; set; }
            /// <summary>
            /// 接收到的时间 
            /// </summary>
            public long time { get; set; }
        }
    }

    2.添加中间件ChatWebSocketMiddleware

    using Dw.Util.Helper;
    using Microsoft.AspNetCore.Http;
    using Newtonsoft.Json;
    using System;
    using System.Collections.Concurrent;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Net.WebSockets;
    using System.Text;
    using System.Threading;
    using System.Threading.Tasks;
    
    namespace Dw.RegApi.Models
    {
        /// <summary>
        /// WebSocket中间件ChatWebSocketMiddleware
        /// </summary>
        public class ChatWebSocketMiddleware
        {
            private static ConcurrentDictionary<string,WebSocket> _sockets = new ConcurrentDictionary<string,WebSocket>();
    
            private readonly RequestDelegate _next;
    
            /// <summary>
            /// WebSocket中间件
            /// </summary>
            /// <param name="next"></param>
            public ChatWebSocketMiddleware(RequestDelegate next)
            {
                _next = next;
            }
    
            /// <summary>
            /// 执行
            /// </summary>
            /// <param name="context"></param>
            /// <returns></returns>
            public async Task Invoke(HttpContext context)
            {
                if (!context.WebSockets.IsWebSocketRequest)
                {
                    await _next.Invoke(context);
                    return;
                }
    
                CancellationToken ct = context.RequestAborted;
                var currentSocket = await context.WebSockets.AcceptWebSocketAsync();

                  string socketId_Expand = Guid.NewGuid().ToString();
                  string socketId = context.Request.Query["sid"].ToString()+ socketId_Expand;

                if (!_sockets.ContainsKey(socketId))
                {
                    _sockets.TryAdd(socketId, currentSocket);
                }
                //_sockets.TryRemove(socketId, out dummy);
                //_sockets.TryAdd(socketId, currentSocket);
    
                while (true)
                {
                    if (ct.IsCancellationRequested)
                    {
                        break;
                    }
    
                    string response = await ReceiveStringAsync(currentSocket, ct);
                    NLogHelper.WriteInfo("WebSocket发送消息:" + response);
                    MsgTemplate msg = JsonConvert.DeserializeObject<MsgTemplate>(response);
    
                    if (string.IsNullOrEmpty(response))
                    {
                        if (currentSocket.State != WebSocketState.Open)
                        {
                            break;
                        }
    
                        continue;
                    }
    
                    foreach (var socket in _sockets)
                    {
                        if (socket.Value.State != WebSocketState.Open)
                        {
                            continue;
                        }
                        //控制只有接收者才能收到消息,并且用户所有的客户端都可以同步收到
                        if (socket.Key.Contains(msg.to_id))
                        {
                            await SendStringAsync(socket.Value, JsonConvert.SerializeObject(msg), ct);
                        }
                    }
                }
    
                //_sockets.TryRemove(socketId, out dummy);
    
                await currentSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "Closing", ct);
                currentSocket.Dispose();
            }
    
            private static Task SendStringAsync(WebSocket socket, string data, CancellationToken ct = default(CancellationToken))
            {
                var buffer = Encoding.UTF8.GetBytes(data);
                var segment = new ArraySegment<byte>(buffer);
                return socket.SendAsync(segment, WebSocketMessageType.Text, true, ct);
            }
    
            private static async Task<string> ReceiveStringAsync(WebSocket socket, CancellationToken ct = default(CancellationToken))
            {
                var buffer = new ArraySegment<byte>(new byte[8192]);
                using (var ms = new MemoryStream())
                {
                    WebSocketReceiveResult result;
                    do
                    {
                        ct.ThrowIfCancellationRequested();
    
                        result = await socket.ReceiveAsync(buffer, ct);
                        ms.Write(buffer.Array, buffer.Offset, result.Count);
                    }
                    while (!result.EndOfMessage);
    
                    ms.Seek(0, SeekOrigin.Begin);
                    if (result.MessageType != WebSocketMessageType.Text)
                    {
                        return null;
                    }
    
                    using (var reader = new StreamReader(ms, Encoding.UTF8))
                    {
                        return await reader.ReadToEndAsync();
                    }
                }
            }
        }
    }

    3.在Startup.cs中使用中间件

                //WebSocket中间件
                var webSocketOptions = new WebSocketOptions()
                {
                    //KeepAliveInterval - 向客户端发送“ping”帧的频率,以确保代理保持连接处于打开状态。 默认值为 2 分钟。
                    KeepAliveInterval = TimeSpan.FromSeconds(120),
                    //ReceiveBufferSize - 用于接收数据的缓冲区的大小。 高级用户可能需要对其进行更改,以便根据数据大小调整性能。 默认值为 4 KB。
                    ReceiveBufferSize = 4 * 1024
                };
                app.UseWebSockets(webSocketOptions);
                app.UseMiddleware<ChatWebSocketMiddleware>();

    相关文档:

    https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/websockets?view=aspnetcore-3.1

    https://www.cnblogs.com/besuccess/p/7043885.html

  • 相关阅读:
    MobaXterm
    记一次完整的java项目压力测试
    jvm调优
    好用的公共dns服务器推荐(免费)
    SpringBoot,Security4, redis共享session,分布式SESSION并发控制,同账号只能登录一次
    javaCV资料目录
    基于JavaCV技术实现RTMP推流和拉流功能
    Java线程池详解
    微服务实战SpringCloud之Feign简介及使用
    【DP专题】——洛谷P5144蜈蚣
  • 原文地址:https://www.cnblogs.com/yechangzhong-826217795/p/13936723.html
Copyright © 2011-2022 走看看