欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

.net core中如何使用websock(页面打开即连接socket通讯)

程序员文章站 2022-05-15 18:43:23
开发的系统有时候需要后端主动的推送数据到前端,有一些方式比如轮询,建立http长连接,websocket主动推送。下面这篇文章主要介绍利用websocket进行主动推送的实现,有人可能说用singleR,我在预研时有了解到实际封装的就是websocket,那我还不如直接用wsk,这样也不会多一层的调用,你们觉得呢!...

开发的系统有时候需要后端主动的推送数据到前端,有一些方式比如轮询,建立http长连接,websocket主动推送。下面这篇文章主要介绍利用websocket进行主动推送的实现,有人可能说用singleR,我在预研时有了解到实际封装的就是websocket,那我还不如直接用wsk,这样也不会多一层的调用,你们觉得呢!

1、首先在core项目中应用websocketserver的组件,通过nuget即可安装进入项目中,搜索安装Microsoft.AspNetCore.WebSockets.Server。

2、在项目中添加一个WebsocketHandlerMiddleware的处理类,监听客户端连接过来的请求,把连接的对象信息进行本地化add保存。

public class WebsocketHandlerMiddleware
    {
        private readonly RequestDelegate _next;
        private readonly ILogger _logger;

        public WebsocketHandlerMiddleware(
            RequestDelegate next,
            ILoggerFactory loggerFactory
            )
        {
            _next = next;
            _logger = loggerFactory.
                CreateLogger<WebsocketHandlerMiddleware>();
        }

        public async Task Invoke(HttpContext context)
        {
            if (context.Request.Path == "/ws")
            {
                if (context.WebSockets.IsWebSocketRequest)
                {
                    WebSocket webSocket = await context.WebSockets.AcceptWebSocketAsync();
                    string clientId = Guid.NewGuid().ToString();  
                    var wsClient = new WebsocketClient
                    {
                        //uuId = clientId,
                        WebSocket = webSocket
                    };
                    try
                    {
                        await Handle(wsClient);
                    }
                    catch (Exception ex)
                    {
                        _logger.LogError(ex, "Echo websocket client {0} err .", clientId);
                        await context.Response.WriteAsync("closed");
                    }
                }
                else
                {
                    context.Response.StatusCode = 404;
                }
            }
            else
            {
                await _next(context);
            }
        }

        private async Task Handle(WebsocketClient webSocket)
        { 
            WebSocketReceiveResult result = null;
            do
            {
                var buffer = new byte[1024 * 2];
                result = await webSocket.WebSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
                if (result.MessageType == WebSocketMessageType.Text && !result.CloseStatus.HasValue)
                {
                    var msgString = Encoding.UTF8.GetString(buffer);
                    _logger.LogInformation($"Websocket client ReceiveAsync message {msgString}.");
                    var message = JsonConvert.DeserializeObject<Message>(msgString);
                    webSocket.uuId = message.ClientId;   
           
                    //MessageRoute(message);

                    WebsocketClientCollection.Add(webSocket);
                    _logger.LogInformation($"Websocket client added.");

                    //SendMsgToClient();
                }
            }
            while (!result.CloseStatus.HasValue);
            WebsocketClientCollection.Remove(webSocket);
            _logger.LogInformation($"Websocket client closed.");
        }
 
        }
    }


3、在startup中添加注册 websocket 服务,当请求为"/ws"走websockt处理handler

app.UseWebSockets(new WebSocketOptions
            {
                KeepAliveInterval = TimeSpan.FromSeconds(60),
                ReceiveBufferSize = 2 * 1024
            });

            app.UseMiddleware<WebsocketHandlerMiddleware>();


4、定义一个客户端的websocket对象,管理websocket的连接对象信息等

public class WebsocketClient
    {

        public WebSocket WebSocket { get; set; }

        public string uuId { get; set; }

     
        public Task SendMessageAsync(string message)
        {
            var msg = Encoding.UTF8.GetBytes(message);
            return WebSocket.SendAsync(new ArraySegment<byte>(msg, 0, msg.Length), WebSocketMessageType.Text, true, CancellationToken.None);
        }
    }
以上基本就是后端的一些处理的主要逻辑,还有粘贴了一些主要的代码示例。一些对象信息可以根据自身项目的业务来进行补充和调整。 下面粘贴的是前端的js示例代码
var socket; //websocket的实例
var wsUrl = "ws://localhost:55565/ws";
function connectWsk() {
    
    socket = new WebSocket(wsUrl);
    socket.onopen = function (evt) {
 
        var message = {
            action: 'join',
            ClientId: $("#uuid").val(), 
        };
        sendmsgwsk(message); 
    };

    socket.onmessage = function (evt) {
        console.log('Connection success.');

        var data = JSON.parse(evt.data);

        // 处理接收的data对象

    };
    socket.onclose = function (evt) {
        console.log('Connection closed.');
        reconnect(wsUrl);
    };
    socket.onerror = function (evt) {
        console.log('websocket服务出错了');
        reconnect(wsUrl);
    };

    // 重新链接
    function reconnect(url) {
        if (lockReconnect) return;
        lockReconnect = true;
        //没连接上会一直重连,设置延迟避免请求过多
        setTimeout(function () {
            connectWsk();
            lockReconnect = false;
        }, 2000);
    }
    //心跳检测
    var heartCheck = {
        timeout: 5000, //5秒发一次心跳检测
        timeoutObj: null,
        serverTimeoutObj: null,
        reset: function () {
            clearTimeout(this.timeoutObj);
            clearTimeout(this.serverTimeoutObj);
            return this;
        },
        start: function () {
            var self = this;
            this.timeoutObj = setTimeout(function () {
                //这里发送一个心跳,后端收到后,返回一个心跳消息,
                //onmessage拿到返回的心跳就说明连接正常
                socket.send("心跳包");
                //如果超过一定时间还没重置,说明后端主动断开了
                self.serverTimeoutObj = setTimeout(function () {
                    //如果onclose会执行reconnect,我们执行ws.close()就行了.
                    //如果直接执行reconnect 会触发onclose导致重连两次
                    socket.close();
                }, self.timeout)
            }, 3000)
        }
    }
}

function closewsk() {
    if (!socket || socket.readyState != WebSocket.OPEN) { 
        console.log('socket服务出错了');
    }
    socket.close(1000, "从客户端关闭");
}

function sendmsgwsk(message) {
    if (!socket || socket.readyState != WebSocket.OPEN) { 
        console.log('socket未连接');
    }

    socket.send(JSON.stringify(message));
}

最后建议做前后端通讯时,分开两个项目进行开发。

以上就是一个前后端的主要介绍,粘贴的示例代码。希望对你的开发有所帮助!

相关标签: websocket core