发布:2020/10/28 17:46:13作者:管理员 来源:本站 浏览次数:1603
最近在公司开发一个小程序时,需要使用到实时通信,然后在网上找了相关资料进行改进和封装,现在把整个DEMO分享出来.组件版本信息:
Asp.Net Core SignalR 1.1.0版本
微信小程序使用腾讯默认的测试APPID,调试基础库基于2.7.1版本
Asp.Net Core SignalR服务端:
1.创建一个项目名为Mango.SignalR.WeChat空模板项目(这里不使用WEBAPI和MVC),这里同时创建一个Chat目录用来存放SignalR的封装类文件
2.使用Nuget引入Microsoft.AspNetCore.SignalR组件包
3.创建好一些基础处理类
说明:
ChatCore类:负责处理消息发送等业务逻辑
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Threading.Tasks; 5 using Microsoft.AspNetCore.SignalR; 6 using Newtonsoft.Json; 7 namespace Mango.SignalR.WeChat.Chat 8 { 9 public class ChatCore 10 { 11 12 /// 13 /// 发送聊天室消息 14 /// 15 /// 16 /// 17 public static void SendMessage(ChatHub chatHub, MessageData messageData) 18 { 19 // 20 var sendMsg = JsonConvert.SerializeObject(messageData); 21 foreach (ConnectionUser user in ConnectionManager.ConnectionUsers) 22 { 23 chatHub.Clients.Client(user.ConnectionId).SendAsync("receive", sendMsg); 24 } 25 } 26 } 27 }
ConnectionUser类:表示连接用户对象
1 using System; 2 using System.Collections.Generic; 3 using System.Text; 4 5 namespace Mango.SignalR.WeChat.Chat 6 { 7 public class ConnectionUser 8 { 9 /// 10 /// 用户标识 11 /// 12 public string UserId { get; set; } 13 /// 14 /// SignalR连接ID 15 /// 16 public string ConnectionId { get; set; } 17 } 18 }
ConnectionManager类:存储用户连接信息
1 using System; 2 using System.Collections.Generic; 3 using System.Text; 4 namespace Mango.SignalR.WeChat.Chat 5 { 6 public class ConnectionManager 7 { 8 public static List ConnectionUsers { get; set; } = new List(); 9 } 10 }
MessageData类:消息体格式定义
1 using System; 2 using System.Collections.Generic; 3 using System.Text; 4 5 namespace Mango.SignalR.WeChat.Chat 6 { 7 public class MessageData 8 { 9 /// 10 /// 消息类型 11 /// 12 public MessageType MessageType { get; set; } 13 /// 14 /// 发送用户(0表示系统消息发送用户) 15 /// 16 public string SendUserId { get; set; } 17 /// 18 /// 消息内容 19 /// 20 public string MessageBody { get; set; } 21 } 22 }
MessageDealWidth类:处理客户端发送的消息
1 using System; 2 using System.Collections.Generic; 3 using System.Text; 4 using System.Linq; 5 using System.Threading; 6 using System.Threading.Tasks; 7 using Microsoft.AspNetCore.SignalR; 8 using Newtonsoft.Json; 9 namespace Mango.SignalR.WeChat.Chat 10 { 11 /// 12 /// 消息处理 13 /// 14 public class MessageDealWidth 15 { 16 public static async Task DealWidth(string message,ChatHub chatHub) 17 { 18 await Task.Run(() => { 19 try 20 { 21 MessageData data = JsonConvert.DeserializeObject(message); 22 if (data != null) 23 { 24 ConnectionUser connectionUser = null; 25 MessageData sendMsg = null; 26 switch (data.MessageType) 27 { 28 case MessageType.Line: 29 connectionUser = ConnectionManager.ConnectionUsers.Where(m => m.ConnectionId == chatHub.Context.ConnectionId).FirstOrDefault(); 30 //处理连接消息 31 if (connectionUser == null) 32 { 33 connectionUser = new ConnectionUser(); 34 connectionUser.ConnectionId = chatHub.Context.ConnectionId; 35 connectionUser.UserId = data.SendUserId; 36 ConnectionManager.ConnectionUsers.Add(connectionUser); 37 } 38 //处理发送回执消息 39 sendMsg = new MessageData(); 40 sendMsg.MessageBody = ""; 41 sendMsg.MessageType = MessageType.LineReceipt; 42 sendMsg.SendUserId = "0"; 43 chatHub.Clients.Client(chatHub.Context.ConnectionId).SendAsync("receive", JsonConvert.SerializeObject(sendMsg)); 44 break; 45 case MessageType.Text: 46 //处理普通文字消息 47 ChatCore.SendMessage(chatHub, data); 48 break; 49 case MessageType.LineReceipt: 50 //处理连接回执消息 51 ChatCore.SendMessage(chatHub, data); 52 break; 53 } 54 } 55 } 56 catch (Exception ex) 57 { 58 Console.WriteLine(ex.Message); 59 } 60 }); 61 } 62 } 63 }
MessageType类:消息类型枚举类
1 using System; 2 3 namespace Mango.SignalR.WeChat.Chat 4 { 5 /// 6 /// 消息类型 7 /// 8 public enum MessageType 9 { 10 /// 11 /// 连接消息 12 /// 13 Line=1, 14 /// 15 /// 文字消息 16 /// 17 Text=2, 18 /// 19 /// 连接回执消息 20 /// 21 LineReceipt = 98, 22 } 23 }
4.创建一个ChatHub的类并且继承Hub父类,代码如下:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Threading.Tasks; 5 using Microsoft.AspNetCore.SignalR; 6 using Newtonsoft.Json; 7 namespace Mango.SignalR.WeChat.Chat 8 { 9 public class ChatHub : Hub 10 { 11 /// 12 /// 服务器端中转消息处理方法 13 /// 14 /// 15 /// 16 public async Task ServerTransferMessage(string message) 17 { 18 await MessageDealWidth.DealWidth(message, this); 19 } 20 /// 21 /// 用户连接方法重写 22 /// 23 /// 24 public override Task OnConnectedAsync() 25 { 26 return base.OnConnectedAsync(); 27 } 28 /// 29 /// 用户断开连接方法重写 30 /// 31 /// 32 /// 33 public override Task OnDisconnectedAsync(Exception exception) 34 { 35 try 36 { 37 var item = ConnectionManager.ConnectionUsers.Where(m => m.ConnectionId == Context.ConnectionId).FirstOrDefault(); 38 //移除相关联用户 39 ConnectionManager.ConnectionUsers.Remove(item); 40 } 41 catch (Exception ex) 42 { 43 throw ex; 44 } 45 return base.OnDisconnectedAsync(exception); 46 } 47 } 48 }
5.在Startup类中添加并且启用SignalR组件
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Threading.Tasks; 5 using Microsoft.AspNetCore.Builder; 6 using Microsoft.AspNetCore.Hosting; 7 using Microsoft.AspNetCore.Http; 8 using Microsoft.Extensions.DependencyInjection; 9 using Mango.SignalR.WeChat.Chat; 10 namespace Mango.SignalR.WeChat 11 { 12 public class Startup 13 { 14 // This method gets called by the runtime. Use this method to add services to the container. 15 // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 16 public void ConfigureServices(IServiceCollection services) 17 { 18 //添加SignalR 19 services.AddSignalR(); 20 } 21 22 // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. 23 public void Configure(IApplicationBuilder app, IHostingEnvironment env) 24 { 25 if (env.IsDevelopment()) 26 { 27 app.UseDeveloperExceptionPage(); 28 } 29 //启用Signalr 30 app.UseSignalR(routes => 31 { 32 routes.MapHub("/ChatHub"); 33 }); 34 app.Run(async (context) => 35 { 36 await context.Response.WriteAsync("SignalR Success!"); 37 }); 38 } 39 } 40 }
6.把SignalR服务端部署到服务器上
PS:由于微信小程序的特殊性需要使用HTTPS,所以这里我已经提供了一个公共测试域名https://123.51core.net
微信小程序端:
1.使用微信开发者工具创建一个用于测试的项目
2.在lib目录中创建signalR.js文件,这个文件封装一个WebSocket处理模块
1 var signalR = (function () { 2 let recordCode = 0x1e; 3 let recordString = String.fromCharCode(recordCode); 4 let isConnectioned = false; 5 let _events=new Array(); 6 //初始化相关事件 7 //消息发送事件 8 _events['send'] = function (obj) { 9 console.log(obj); 10 }; 11 //消息接收事件 12 _events['receive']=function(message){ 13 console.log(message); 14 }; 15 //连接事件 16 _events['connection']= function () { 17 console.log(message); 18 }; 19 //连接关闭事件 20 _events['close']= function () { 21 console.log('连接已经关闭'); 22 }; 23 //连接异常处理事件 24 _events['error'] = function (ex) { 25 console.log(ex); 26 }; 27 return { 28 //事件绑定 29 on:function(eventName,eventMethod){ 30 if (_events[eventName] != null && _events[eventName]!=undefined){ 31 _events[eventName] = eventMethod; 32 } 33 }, 34 //连接方法 35 connection: function (url) { 36 let self = this; 37 wx.connectSocket({ 38 url: url 39 }); 40 wx.onSocketOpen(function () { 41 let handshakeRequest = { 42 protocol: 'json', 43 version: 1 44 }; 45 let senddata = `${JSON.stringify(handshakeRequest)}${recordString}`; 46 self.isConnectioned = true; 47 wx.sendSocketMessage({ 48 data: senddata, 49 }); 50 _events['connection'](); 51 }); 52 wx.onSocketClose(function () { 53 self.isConnectioned = false; 54 _events['close'](); 55 }); 56 //接收到消息 57 wx.onSocketMessage(function (res) { 58 try { 59 //console.log(res); 60 let jsonstr = String(res.data).replace(recordString, ''); 61 if (jsonstr.indexOf('{}{') > -1){ 62 jsonstr = jsonstr.replace('{}', ''); 63 } 64 let obj = JSON.parse(jsonstr); 65 //当收到返回消息type=1(调用方法) 66 if (obj.type == 1) { 67 _events['receive'](obj.arguments[0]); 68 } 69 } catch (ex) { 70 console.log('异常:' + ex); 71 console.log('收到服务器内容:' + res.data); 72 } 73 }); 74 wx.onSocketError(function (ex) { 75 self.isConnectioned = false; 76 _events['error'](ex); 77 }); 78 }, 79 abortConnection: function () { 80 console.log(String(this.abortConnection.name)); 81 wx.closeSocket(); 82 }, 83 sendMessage: function (data) { 84 let self = this; 85 if (!self.isConnectioned) { 86 _events['error']('未连接'); 87 return; 88 } 89 let args=new Array(); 90 args.push(data); 91 let body = { 92 arguments: args, //SignalR服务端接收时必须为数组参数 93 target: 'ServerTransferMessage', //SignalR端方法 94 type: 1, 95 }; 96 //发送的数据,分隔符结尾: 97 let senddata = `${JSON.stringify(body)}${recordString}`; 98 wx.sendSocketMessage({ 99 data: senddata, 100 success: function(res){ 101 _events['send'](res); 102 }, 103 fail: function(ex){ 104 console.log(ex); 105 } 106 }); 107 } 108 } 109 }); 110 module.exports = { 111 signalR: signalR 112 }
2.在index.js中调用
1 //index.js 2 ///引入这个类库 3 var signalR = require('../../lib/signalR.js') 4 //获取应用实例 5 const app = getApp() 6 7 Page({ 8 data: { 9 motto: '微信连接SignalR的Demo' 10 }, 11 onLoad: function () { 12 //测试WebSocket 13 ///实例化一个对象 14 let _signalR = new signalR.signalR(); 15 _signalR.on("receive", function (message) { 16 console.log('服务器返回消息回调方法:' + message); 17 }); 18 _signalR.on("connection", function () { 19 //消息格式 20 var msg = { 21 messageType: 1,//消息类型 1.发送连接消息 2.普通内容消息 98.连接回执消息 22 sendUserId: '1',//消息发送人(登录用户ID) 23 messageBody: 'online'//消息内容 24 }; 25 _signalR.sendMessage(JSON.stringify(msg)); 26 }); 27 _signalR.connection('wss://123.51core.net/ChatHub'); 28 } 29 })
接下来就可以查看运行结果了,如下图:
本案例源代码已经更新到github上,欢迎大家下载
https://github.com/51core/mango-docs
© Copyright 2014 - 2024 柏港建站平台 ejk5.com. 渝ICP备16000791号-4