来源:https://blog.csdn.net/i2blue/article/details/125288034
Program.cs
#region WebSockets
// https://learn.microsoft.com/zh-cn/aspnet/core/fundamentals/websockets?view=aspnetcore-7.0
// 启用WebSockets,
// KeepAliveInterval - 向客户端发送“ping”帧的频率,以确保代理保持连接处于打开状态。
// 默认值为 2 分钟。
// AllowedOrigins - 用于 WebSocket 请求的允许的 Origin 标头值列表。
// 默认情况下,允许使用所有源。 有关详细信息,请参阅本文中的 WebSocket 源限制。
var webSocketOptions = new WebSocketOptions
{
    KeepAliveInterval = TimeSpan.FromMinutes(2)
};
// 设置允许WebSocket连接的来源地址
//webSocketOptions.AllowedOrigins.Add("https://client.com");
//webSocketOptions.AllowedOrigins.Add("https://www.client.com");
app.UseWebSockets(webSocketOptions);

//app.Use(async (context, next) =>
//{
//    if (context.Request.Path == "/ws")
//    {
//        if (context.WebSockets.IsWebSocketRequest)
//        {
//            using var webSocket = await context.WebSockets.AcceptWebSocketAsync();
//            await Echo(webSocket);
//        }
//        else
//        {
//            context.Response.StatusCode = StatusCodes.Status400BadRequest;
//        }
//    }
//    else
//    {
//        await next(context);
//    }
//});
#endregion

 controller版

public class WebSocketCenterController : Controller
    {
        private readonly ILogger<WebSocketCenterController> _logger;

        public WebSocketCenterController(ILogger<WebSocketCenterController> logger)
        {
            _logger = logger;
        }

        //原文链接:https://blog.csdn.net/i2blue/article/details/125288034
        [HttpGet("/ws")]
        public async Task WebSocketServer()
        {
            // 判断为WebSocket请求
            if (HttpContext.WebSockets.IsWebSocketRequest)
            {
                try
                {
                    var socket = await HttpContext.WebSockets.AcceptWebSocketAsync();
                    await new WebSocketHelper().WebSocketReceive(socket);
                }
                catch (Exception ex)
                {
                    _logger.LogError(ex, "WebSocketException");
                }
            }
        }
    }

WebSocketHelper

public class WebSocketHelper
    {
        public async Task WebSocketReceive(WebSocket webSocket)
        {
            StringBuilder receiveBuilder = new StringBuilder();
            var id = Guid.NewGuid().ToString("N");
            //var buffer = ArrayPool<byte>.Shared.Rent(10);
            int byteLen = 10;//每次读取的字节数
            var tempBuffs = new byte[byteLen];
            List<byte> data = new List<byte>();
            try
            {
                //循环接收,每次接收固定长度的字节。
                while (webSocket.State == WebSocketState.Open)
                {
                    var result = await webSocket.ReceiveAsync(tempBuffs, CancellationToken.None);
                    if (result.MessageType == WebSocketMessageType.Close)
                    {
                        throw new WebSocketException(WebSocketError.ConnectionClosedPrematurely, result.CloseStatusDescription);
                    }
                    //读取字节数小于字节数组长度,则说明数据已读取完毕。
                    if (result.Count < byteLen)
                    {
                        for (int i = 0; i < result.Count; i++)
                        {
                            data.Add(tempBuffs[i]);
                        }
                        //读取结束
                        var dataArray = data.ToArray();
                        //dataArray.AsSpan(0, dataArray.Length)
                        var text = Encoding.UTF8.GetString(dataArray);
                        var sendStr = Encoding.UTF8.GetBytes($"服务端 {id} : {text}  -{DateTime.Now}");
                        await webSocket.SendAsync(sendStr, WebSocketMessageType.Text, true, CancellationToken.None);
                        data.Clear();
                    }
                    else
                    {
                        data.AddRange(tempBuffs.ToList());
                    }
                }
            }
            finally
            {
                //ArrayPool<byte>.Shared.Return(buffer);
                tempBuffs = null;
                data.Clear();
            }
        }

        /// <summary>
        /// 创建客户端实例
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public static async Task<ClientWebSocket> CreateAsync(string ServerUri)
        {
            var webSocket = new ClientWebSocket();
            webSocket.Options.RemoteCertificateValidationCallback = delegate { return true; };

            await webSocket.ConnectAsync(new Uri(ServerUri), CancellationToken.None);
            if (webSocket.State == WebSocketState.Open)
            {
                return webSocket;
            }
            return null;
        }

    }

后端调用

[HttpPost]
        public async Task<IActionResult> Test()
        {
            ApiResult<string> result = new ApiResult<string>();
            try
            {
                var webSocket = await WebSocketHelper.CreateAsync("ws://localhost:5196/ws");
                if (webSocket != null)
                {
                    Func<Task<string>> task = new Func<Task<string>>(async () =>
                    {
                        int byteLen = 10;//每次读取的字节数
                        var tempBuffs = new byte[byteLen];
                        List<byte> data = new List<byte>();
                        string dataStr = "";
                        try
                        {
                            while (webSocket.State == WebSocketState.Open)
                            {
                                var result = await webSocket.ReceiveAsync(tempBuffs, CancellationToken.None);
                                if (result.MessageType == WebSocketMessageType.Close)
                                {
                                    throw new WebSocketException(WebSocketError.ConnectionClosedPrematurely, result.CloseStatusDescription);
                                }
                                //读取字节数小于字节数组长度,则说明数据已读取完毕。
                                if (result.Count < byteLen)
                                {
                                    for (int i = 0; i < result.Count; i++)
                                    {
                                        data.Add(tempBuffs[i]);
                                    }
                                    //读取结束
                                    var dataArray = data.ToArray();
                                    dataStr = Encoding.UTF8.GetString(dataArray);
                                    break;
                                }
                                else
                                {
                                    data.AddRange(tempBuffs.ToList());
                                }
                            }
                        }
                        catch (Exception ex)
                        {
                            return ex.Message;
                        }
                        finally
                        {
                            //ArrayPool<byte>.Shared.Return(buffer);
                            tempBuffs = null;
                            data = null;
                        }
                        return dataStr;
                    });

                    var sendStr = Encoding.UTF8.GetBytes("客户端发送数据");
                    await webSocket.SendAsync(sendStr, WebSocketMessageType.Text, true, CancellationToken.None);

                    var dataRes = await Task.Run(task);

                    result.ErrorCode = "0";
                    result.Data = dataRes;
                    result.Message = "success";
                }
                else
                {
                    result.ErrorCode = "-1";
                    result.Data = "服务连接失败!";
                    result.Message = "failed";
                }
                return Json(result);

            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "##服务连接异常");
                ViewData["Msg"] = ex.Message;
                result.ErrorCode = "-1";
                result.Message = ex.Message;
                return Json(result);
            }
        }

前端调用
html

<div id="message" style="border: solid 1px #333; padding: 4px; width: 550px; overflow: auto; background-color: #404040; height: 300px; margin-bottom: 8px; font-size: 14px;">
</div>
<textarea id="txtDes" cols="80" rows="10"></textarea>
<br />
<button id="send" onclick="send();">发送</button>
<button onclick="quit();">停止</button>
<button onclick="testSocket()">test</button>

js

///////////////////////////////////////////////////////
        //var ws;
        //var msgContainer = document.getElementById('message');
        //window.onload = function () {
        //    ws = new WebSocket("ws://localhost:5196/ws");
        //    ws.onopen = function (e) {
        //        var msg = document.createElement('div');
        //        msg.style.color = '#0f0';
        //        msg.innerHTML = "Server > connection open.";
        //        msgContainer.appendChild(msg);
        //    };
        //    ws.onmessage = function (e) {
        //        var msg = document.createElement('div');
        //        msg.style.color = '#0f0';
        //        msg.innerHTML = e.data;
        //        msgContainer.appendChild(msg);
        //        msgContainer.scrollTop = msgContainer.scrollHeight;
        //    };
        //    ws.onerror = function (e) {
        //        var msg = document.createElement('div');
        //        msg.style.color = '#0f0';
        //        msg.innerHTML = 'Server > ' + e.data;
        //        msgContainer.appendChild(msg);
        //    };
        //    ws.onclose = function (e) {
        //        var msg = document.createElement('div');
        //        msg.style.color = '#0f0';
        //        msg.innerHTML = 'Server > connection closed.';
        //        msgContainer.appendChild(msg);
        //        ws = null;
        //    };
        //}
        //function quit() {
        //    if (ws) {
        //        ws.close();
        //        var msg = document.createElement('div');
        //        msg.style.color = '#0f0';
        //        msg.innerHTML = 'Server >start closed.';
        //        msgContainer.appendChild(msg);
        //        ws = null;
        //    }
        //}
        //function send() {
        //    var dataStr = $("#txtDes").val();
        //    ws.send(dataStr);
        //    var htmlValue = "客户端: " + dataStr + "  " + getNowTime();
        //    var msg = document.createElement('div');
        //    msg.style.color = '#ffff00';
        //    msg.innerHTML = htmlValue;
        //    msgContainer.appendChild(msg);
        //    $("#txtDes").val("");
        //    msgContainer.scrollTop = msgContainer.scrollHeight;
        //}
        ////获取当前时间
        //function getNowTime() {
        //    var date = new Date();
        //    //年 getFullYear():四位数字返回年份
        //    var year = date.getFullYear(); //getFullYear()代替getYear()
        //    //月 getMonth():0 ~ 11
        //    var month = date.getMonth() + 1;
        //    //日 getDate():(1 ~ 31)
        //    var day = date.getDate();
        //    //时 getHours():(0 ~ 23)
        //    var hour = date.getHours();
        //    //分 getMinutes(): (0 ~ 59)
        //    var minute = date.getMinutes();
        //    //秒 getSeconds():(0 ~ 59)
        //    var second = date.getSeconds();
        //    var time = year + '/' + addZero(month) + '/' + addZero(day) + ' ' + addZero(hour) + ':' + addZero(minute) + ':' + addZero(second);
        //    return time;
        //}
        ////小于10的拼接上0字符串
        //function addZero(s) {
        //    return s < 10 ? ('0' + s) : s;
        //}

        //function testSocket(){
        //    $.ajax({
        //        url: "/Home/Test",
        //        type: "post",
        //        dataType: "json",
        //        contentType: "application/json",
        //        //data: JSON.stringify({ Idx: 1, ProductCode: "code1", ProductName: "name1", StockQty: 10, MakeQty: 4 }),
        //        success: function (result, status) {
        //            alert(result.message + "/" + result.data);
        //        }
        //    });
        //}
        ///////////////////////////////////////////////////////

WebSocket中间件版本

using WebApp.Utils;

namespace WebApp.Middlewares
{
    /// <summary>
    /// webSocket
    /// </summary>
    public class WebSocketMiddleware
    {
        private readonly RequestDelegate _next;
        private readonly ILogger<ExceptionHandlingMiddleware> _logger;

        /// <summary>
        /// 构造
        /// </summary>
        /// <param name="next"></param>
        /// <param name="actionPathName">目标路径</param>
        public WebSocketMiddleware(RequestDelegate next, ILogger<ExceptionHandlingMiddleware> logger)
        {
            _next = next;
            _logger = logger;
        }
        /// <summary>
        /// 中间件调用
        /// </summary>
        /// <param name="httpContext"></param>
        /// <returns></returns>
        public async Task Invoke(HttpContext httpContext)
        {
            try
            {
                var socket = await httpContext.WebSockets.AcceptWebSocketAsync();
                await new WebSocketHelper().WebSocketReceive(socket);
            }
            catch (Exception ex)
            {
                //调用日志处理对象的实例记录日志
                _logger.LogError(ex, "##异常来源:{0}", httpContext.Request.Path);
            }
            await _next(httpContext);
        }
    }

    // Extension method used to add the middleware to the HTTP request pipeline.
    public static class WebSocketMiddlewareExtensions
    {
        public static IApplicationBuilder UseWebSocketMiddleware(this IApplicationBuilder builder)
        {
            return builder.UseMiddleware<WebSocketMiddleware>();
        }
    }
}

 中间件,Program.cs中 app.UseWebSocketMiddleware();

posted on 2023-04-12 10:45  邢帅杰  阅读(245)  评论(0编辑  收藏  举报