.Net Core+Web简单实现WebSocket(点对点,点对多通讯)

本文介绍了如何使用C#创建一个WebSocket中间件WebSocketMiddleware,实现在Web应用中模拟网页版微信的实时通讯功能,包括处理WebSocket请求、用户连接管理以及前端HTML+JS的交互示例。
摘要由CSDN通过智能技术生成

需求:模拟网页版微信进行通讯

直接上代码:

服务类:WebSocketMiddleware
public class WebSocketMiddleware
    {
        private readonly RequestDelegate _next;
        public  static Dictionary<string, WebSocket> _userConnections = new Dictionary<string, WebSocket>();

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

        public async Task InvokeAsync(HttpContext context)
        {
            if (!context.WebSockets.IsWebSocketRequest)
            {
                await _next(context);
                return;
            }
            
            WebSocket webSocket = await context.WebSockets.AcceptWebSocketAsync();
            string UserId = context.Request.Query["UserId"].ToString();
            // 将用户ID和WebSocket连接添加到映射中
            _userConnections[UserId] = webSocket;
            try
            {
                // 处理WebSocket消息
                await HandleWebSocketMessages(UserId, webSocket);
            }
            catch (Exception e)
            {
                //写入日志
                var bb = e.Message;
            }
            //移除WebSockets集合
            if (_userConnections.ContainsKey(UserId))
            {
                _userConnections.Remove(UserId);
            }
            
        }

        private async Task HandleWebSocketMessages(string SenderId, WebSocket webSocket)
        {
            var buffer = new byte[1024 * 4];
            WebSocketReceiveResult result;

            while (webSocket.State == WebSocketState.Open)
            {
                result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
                if (result.CloseStatus.HasValue)
                {
                    // 关闭WebSocket连接
                    await webSocket.CloseAsync(result.CloseStatus.Value, result.CloseStatusDescription, CancellationToken.None);
                    return;
                }
                // 解析接收到的消息,获取发送者和接收者ID
                // 假设消息格式是一个JSON对象,包含"from", "to", 和 "content"字段
                var message = Encoding.UTF8.GetString(buffer, 0, result.Count);
                var messageObj = JsonConvert.DeserializeObject<Message>(message);
                if (messageObj == null) return;
                //发送者标识,由后端这里进行补充或替换
                messageObj.SenderId = SenderId;


                // 如果是广播消息(to字段为空或特定值),则发送给所有用户
                if (string.IsNullOrEmpty(messageObj.TargetId) || messageObj.TargetId == "0")
                {
                    foreach (var connection in _userConnections.Values)
                    {
                        if (connection != webSocket) // 不要将消息发送回发送者
                        {
                            await connection.SendAsync(new ArraySegment<byte>(buffer, 0, result.Count), result.MessageType, result.EndOfMessage, CancellationToken.None);
                        }
                    }
                }
                else
                {
                    // 如果是点对点消息,则根据接收者ID路由到正确的连接
                    if (_userConnections.TryGetValue(messageObj.TargetId, out WebSocket targetWebSocket))
                    {
                        await targetWebSocket.SendAsync(new ArraySegment<byte>(buffer, 0, result.Count), result.MessageType, result.EndOfMessage, CancellationToken.None);
                    }
                }
            }
        }

        // 假设的Message类来表示WebSocket消息
        private class Message
        {
            /// <summary>
            /// 发送者标识
            /// </summary>
            public string SenderId { get; set; }
            /// <summary>
            /// 接受者标识
            /// </summary>
            public string TargetId { get; set; }
            /// <summary>
            /// 消息内容
            /// </summary>
            public string Content { get; set; }
            /// <summary>
            /// 表单内容
            /// </summary>
            public string From { get; set; }
        }
        
    }
中间件:Startup.cs
public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers();
}

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
        app.UseWebSockets();
        app.Map("/OAWebSocket", (appWebSocket) =>
         {
              appWebSocket.UseMiddleware<WebSocketMiddleware>();
         });
}
API:WebSocketController.cs
using Ht.Cloud.Common;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.WebSockets;

namespace Ht.Cloud.Api.Controllers.Common
{
    /// <summary>
    /// websocket
    /// </summary>
    [Route("[controller]/[action]")]
    [ApiController]
    public class WebSocketController : ControllerBase
    {
        /// <summary>
        /// 
        /// </summary>
        private  Dictionary<string, WebSocket> _userConnections;
        public WebSocketController()
        {
            _userConnections = new Dictionary<string, WebSocket>();
            _userConnections = WebSocketMiddleware._userConnections;
            // 假设你有代码来维护_userConnections字典
        }
        /// <summary>
        /// 获取WebSocket的连接人数
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public int GetSumUser()
        {
            return _userConnections.Count;
        }
        

    }
}
HTML+JS:Model.html
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title></title>
    <script src="../../js/jquery-3.3.1.js"></script>

    <script>
        var socket;


        function star(index) {
            //wws为https,如果是http改为ws,OAWebSocket为后端Startup中间件的配置(app.Map("/OAWebSocket",),UserId传输链接的用户标识
            socket = new WebSocket('wss://localhost:44360/OAWebSocket?UserId=' + index + '');
            textarea = document.getElementById('TextArea' + index + '')
            socket.onopen = function (event) {

                textarea.value += '用户标识' + index + ',已连接到WebSocket服务器:' + '\n';
                //socket.send('你好,服务器!');
            };

            socket.onmessage = function (event) {

                textarea.value += '接收消息:' + event.data + '\n';
            };

            socket.onclose = function (event) {

                textarea.value += '用户标识' + index + ',已断开与WebSocket服务器的连接' + '\n';
            };

            socket.onerror = function (error) {

                textarea.value += 'WebSocket Error:' + error + '\n';
            };
        }
        function send() {
            var Text1 = document.getElementById('Text1');
            var Message = JSON.stringify({ "SenderId": "", "TargetId": "", "Content": Text1.value, "From": "" });
            var textarea = document.getElementById('TextArea1');
            textarea.value += "发送消息:" + Message + '\n';
            socket.send(Message);
        }
        function send1() {
            var Text2 = document.getElementById('Text2');
            var Message = JSON.stringify({ "SenderId": "", "TargetId": "", "Content": Text2.value, "From": "" });
            var textarea = document.getElementById('TextArea2');
            textarea.value += "发送消息:" + Message + '\n';
            socket.send(Message);
        }
        // 当需要关闭WebSocket连接时
        function end() {
            if (socket.readyState === WebSocket.OPEN) {
                socket.close(); // 发送关闭帧给服务器
            }
        }
    </script>
    <script>
        setInterval(updateUserCount, 5000); // 每5秒更新一次
        function updateUserCount() {
            fetch('https://localhost:44360/WebSocket/GetSumUser') // 调用后端API
                .then(response => response.json()) // 解析返回的JSON
                .then(data => {
                    // 假设你有一个元素用于显示用户数,例如<span id="userCount"></span>
                    document.getElementById('userCount').textContent = data; // 更新页面上的用户数
                })
                .catch(error => {
                    console.error('Error:', error);
                });
        }
    </script>
</head>
<body>
    当前连接人数<span id="userCount">0</span>
    <br />

    <input id="btn-kslj" type="button" onclick="star(1)" value="客户端标识1,开始连接" /><input id="btn-gb" type="button" onclick="end()" value="关闭链接" /><br />
    接收内容:<textarea id="TextArea1" rows="2" style="width:600px; height:300px;" cols="20"></textarea>
    发送内容:<input id="Text1" type="text" />
    <input id="fasong" type="button" onclick="send()" value="发送" />



    <br />

    <input id="btn-kslj2" type="button" onclick="star(2)" value="客户端标识2,开始连接" /><br />
    接收内容:<textarea id="TextArea2" rows="2" style="width:600px; height:300px;" cols="20"></textarea>
    发送内容:<input id="Text2" type="text" />
    <input id="fasong" type="button" onclick="send1()" value="发送" />


</body>
</html>

  • 7
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
.NET Core Web Api中,你可以使用SignalR来实现WebSocket通信。SignalR提供了一种简单的方式来处理WebSocket连接和消息的接收和发送,同时也支持其他传输协议,如Server-Sent Events和Long Polling。 要使用SignalR,你需要安装Microsoft.AspNetCore.SignalR包。你可以使用NuGet包管理器或在项目文件中手动添加依赖项。在安装完成后,你可以创建一个Hub类来处理WebSocket连接和消息的接收和发送。 例如,你可以创建一个名为ChatHub的类: ```csharp using Microsoft.AspNetCore.SignalR; using System.Threading.Tasks; public class ChatHub : Hub { public async Task SendMessage(string user, string message) { await Clients.All.SendAsync("ReceiveMessage", user, message); } } ``` 在上面的代码中,SendMessage方法用于接收客户端发送的消息,并使用Clients.All.SendAsync方法向所有连接的客户端发送消息。ReceiveMessage是客户端用于接收消息的方法名称。 现在,你需要在Startup.cs文件中配置SignalR中间件。在ConfigureServices方法中,你需要添加SignalR服务: ```csharp services.AddSignalR(); ``` 在Configure方法中,你需要将SignalR中间件添加到请求管道中: ```csharp app.UseSignalR(routes => { routes.MapHub<ChatHub>("/chatHub"); }); ``` 在上面的代码中,/chatHub是WebSocket的URL路径,ChatHub是你创建的Hub类。 最后,在客户端中,你需要使用SignalR客户端库来连接到WebSocket,并使用on方法来接收服务器发送的数据。 例如,你可以使用如下代码连接到ChatHub: ```javascript import * as signalR from "@microsoft/signalr"; const connection = new signalR.HubConnectionBuilder() .withUrl("/chatHub") .build(); connection.start().then(() => { console.log("WebSocket connected"); }); export default connection; ``` 然后,你可以使用on方法接收服务器发送的数据: ```javascript import connection from "./connection"; connection.on("ReceiveMessage", (user, message) => { console.log(user + " says: " + message); }); ``` 这样,你就可以使用SignalR在.NET Core Web Api中配置WebSocket通信了。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值