.net core中如何使用websock(页面打开即连接socket通讯)
程序员文章站
2022-04-11 11:29:49
开发的系统有时候需要后端主动的推送数据到前端,有一些方式比如轮询,建立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)); }
最后建议做前后端通讯时,分开两个项目进行开发。
以上就是一个前后端的主要介绍,粘贴的示例代码。希望对你的开发有所帮助!