安装
注:1.本地使用控制台启动调试时 如果地址用了ip需要用管理员身份运行项目,如果使用localhost则不需要
2.客户端必须要有一个方法
安装自托管包 install-package Microsoft.AspNet.SignalR.SelfHost 第一步
安装跨域包 Install-Package Microsoft.Owin.Cors 第二步
Install-Package Microsoft.AspNet.SignalR
–install-package Microsoft.Owin.Host.HttpListener
–install-package Microsoft.Owin.Hosting
–应用程序作为客户端时的中间件 Install-Package Microsoft.AspNet.SignalR.Client
–https
netsh http add sslcert ipport=0.0.0.0:8082
appid={12345678-db90-4b66-8b01-88f7af2e36bf}
certhash=d37b844594e5c23702ef4e6bd17719a079b9bdf
netsh http show sslcert ipport=0.0.0.0:8082
MainHub.cs 类
using Microsoft.AspNet.SignalR;
using Microsoft.AspNet.SignalR.Hubs;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
namespace MyHub
{
[MyHubAuthorize]
public class MainHub : Hub
{
/// <summary>
/// 事件 接收客户端消息
/// </summary>
public static event Action<HubCallerContext,string> ReceivedData;
/// <summary>
/// 事件 新链接
/// </summary>
public static event Action<HubCallerContext> NewConnected;
public static ConcurrentDictionary<string, HubCallerContext> ConnectionDictionary = new ConcurrentDictionary<string, HubCallerContext>();
/// <summary>
/// 服务端方法 提供给客户端调用,从客户端传递消息到服务端
/// </summary>
/// <param name="data"></param>
public void FromClient(string data)
{
ReceivedData?.Invoke(Context, data);
}
/// <summary>
/// 服务端方法 提供给服务端调用,从服务端传递消息到客户端 传给指定客户端
/// </summary>
/// <param name="ConnectionId"></param>
/// <param name="data"></param>
public static void ToClient(string ConnectionId, object data)
{
var t = Task.Factory.StartNew(() =>
{
try
{
GlobalHost.ConnectionManager.GetHubContext<MainHub>().Clients.Client(ConnectionId).OnMessage(data);//调用客户端OnMessage()方法
//this.Clients.Client(ConnectionId).OnMessage(data);
}
catch (Exception e)
{
}
});
}
/// <summary>
/// 服务端方法 提供给服务端调用,调用客户端OnStop()方法 从客户端断开链接
/// </summary>
/// <param name="ConnectionId"></param>
public static void CloseClient(string ConnectionId)
{
GlobalHost.ConnectionManager.GetHubContext<MainHub>().Clients.Client(ConnectionId).OnStop();//调用客户端OnStop()方法 从客户端断开链接
//this.Clients.Client(ConnectionId).OnMessage(data);
}
/// <summary>
/// 服务端方法 提供给服务端调用,从服务端传递消息到客户端 传给所有客户端
/// </summary>
/// <param name="data"></param>
public static void ToClient(object data)
{
var t = Task.Factory.StartNew(() =>
{
try
{
GlobalHost.ConnectionManager.GetHubContext<MainHub>().Clients.All.OnMessage(data);
//Clients.All.OnMessage(data);
}
catch (Exception e)
{
}
});
}
public override Task OnConnected()
{
try
{
if (!ConnectionDictionary.ContainsKey(Context.ConnectionId))
{
//Clients.Caller.OnStop();
if(!ConnectionDictionary.TryAdd(Context.ConnectionId, Context))
{
Clients.Caller.OnStop();
}
}
string QueryString = "";
foreach (var item in Context.QueryString)
{
if (item.Key != "connectionToken")
{
QueryString += item.Key + ":" + item.Value + " ";
}
}
}
catch
{
}
NewConnected?.Invoke(Context);
return base.OnConnected();
}
public override Task OnReconnected()
{
try
{
if (!ConnectionDictionary.ContainsKey(Context.ConnectionId))
{
if (!ConnectionDictionary.TryAdd(Context.ConnectionId, Context))
{
Clients.Caller.OnStop();
}
}
}
catch
{
}
NewConnected?.Invoke(Context);
return base.OnReconnected();
}
public override Task OnDisconnected(bool stopCalled)
{
try
{
if (ConnectionDictionary.ContainsKey(Context.ConnectionId))
{
HubCallerContext outval;
ConnectionDictionary.TryRemove(Context.ConnectionId, out outval);
}
}
catch
{
}
return base.OnDisconnected(stopCalled);
}
}
}
MyHubAuthorize.cs 过滤器类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNet.SignalR;
using Microsoft.AspNet.SignalR.Hubs;
namespace MyHub
{
public class MyHubAuthorize: AuthorizeAttribute
{
/// <summary>
/// 连接权限
/// </summary>
/// <param name="hubDescriptor"></param>
/// <param name="request"></param>
/// <returns>true 允许连接 触发OnConnected false 不允许连接</returns>
public override bool AuthorizeHubConnection(HubDescriptor hubDescriptor, IRequest request)
{
return true;
}
/// <summary>
/// 调用服务端方法权限
/// </summary>
/// <param name="hubIncomingInvokerContext"></param>
/// <param name="appliesToMethod"></param>
/// <returns></returns>
public override bool AuthorizeHubMethodInvocation(IHubIncomingInvokerContext hubIncomingInvokerContext, bool appliesToMethod)
{
return true;
}
}
}
Startup.cs
using Microsoft.AspNet.SignalR;
using Microsoft.Owin;
using Microsoft.Owin.Cors;
using Owin;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
[assembly: OwinStartup(typeof(Server.Startup))]
namespace Server
{
public class Startup
{
public void Configuration(IAppBuilder app)
{
//开启cors
app.UseCors(CorsOptions.AllowAll);
//开启JSONP,并显示详细问题
var config = new HubConfiguration() { EnableJSONP = true, EnableDetailedErrors = true };
app.MapSignalR(config);
}
}
}
业务逻辑层调用 BLL
#define Release
//#define必须放在最顶部 Release 调试模式标志 Debug 发布模式标志 Release
using SuperWebSocket;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Microsoft.Owin.Hosting;
using MyHub;
using Microsoft.AspNet.SignalR.Hubs;
namespace BLL
{
public class SignalRServerBLL
{
private bool _isRunning = true;
private Thread _MainThread = null;
private int _SleepTime = 0;
private string _HttpListenerUrl = Properties.Settings1.Default.HttpListenerUrl;
private IDisposable _web_app;
public SignalRServerBLL()
{
try
{
_MainThread = new Thread(new ThreadStart(Process));
MainHub.ReceivedData += my_ReceivedData;
MainHub.NewConnected += my_NewConnected;
}
catch (Exception ex)
{
Service1.logger.Error(ex.ToString());
}
}
public void Start()
{
try
{
//本地使用控制台启动调试时 如果地址用了ip需要用管理员身份运行项目(管理员身份运行VS),如果使用localhost则不需要
_web_app = WebApp.Start<Startup>(_HttpListenerUrl);
_MainThread.Start();
Service1.logger.Info(string.Format("Service Start {0}...", _web_app!=null?"Success":"Fail"));
Service1.logger.Info($"HttpListenerUrl {_HttpListenerUrl}...");
}
catch (Exception ex)
{
#if Debug
throw;
#endif
Service1.logger.Error(ex.ToString());
}
}
public void Dispose()
{
_isRunning = false;
_web_app?.Dispose();
Service1.logger.Info("Service Dispose...");
}
#region
/// <summary>
/// 新连接处理
/// </summary>
/// <param name="session"></param>
private void my_NewConnected(HubCallerContext Context)
{
try
{
//do..
}
catch (Exception ex)
{
#if Debug
throw;
#endif
Service1.logger.Error(ex.ToString());
}
}
/// <summary>
/// 消息处理
/// </summary>
/// <param name="session"></param>
/// <param name="data"></param>
private void my_ReceivedData(HubCallerContext Context, string data)
{
try
{
//do..
//var Path_eng = MainHub.ConnectionDictionary.Where(C => C.Value.QueryString["Language"] != null && C.Value.QueryString["Language"].ToString().ToLower() == "eng");
MainHub.ToClient(Context.ConnectionId, data);
}
catch (Exception ex)
{
#if Debug
throw;
#endif
Service1.logger.Error(ex.ToString());
}
}
#endregion
#region
private void Process()
{
do
{
//do..
Thread.Sleep(_SleepTime);
} while (_isRunning);
}
#endregion
}
}
网页客户端
mySignalR.js
//創建SingnalR公共模型 LCJ 2018年4月13日11:30:57
var mySignalR = function () {
this.Hub = null;//集線器
this.Proxy = null;//代理
this.Url = null;//鏈接地址
this.QueryString = {};//請求參數
this.OnEven = {};//客戶端事件
this.stateChanged = null;//鏈接狀態改變事件
};
mySignalR.prototype.SendMessage = function (data) {//客戶端發送消息到服務器方法
//调用 server 端的方法 服务端要有方法“FromClient”
this.Proxy.invoke("FromClient", data).done(function (msg) {
console.log(msg);
}).fail(function (data) {
console.log(data);
});
};
mySignalR.prototype.Start = function () {//初始化,啟動鏈接
if (this.Proxy != null) return;//防止多次调用Start() 开启多个链接
var Conn = $.hubConnection(this.Url);
Conn.qs = this.QueryString;
//代理
this.Proxy = Conn.createHubProxy(this.Hub);
//定义客户端方法(必须要有一个)
for (var myEven in this.OnEven) {//批量註冊客戶端方法
this.Proxy.on(myEven, this.OnEven[myEven]);
}
//this.Proxy.on("OnMessage", this.OnMessage);
this.Proxy.on("OnStop", function () {
this.stop();
});
Conn.connectionSlow(function () {
console.log("connectionSlow");
});
Conn.stateChanged(this.stateChanged);
Conn.reconnecting(function () {
console.log("重新连接中");
});
Conn.reconnected(function () {
console.log("重新连接成功");
});
Conn.disconnected(function () {
console.log("连接中断");
((CurrentConn)=>{
//this 當前conn對象
setTimeout(()=>{ CurrentConn.start(); }, 5000);
})(this);
});
Conn.error(function (error) {
console.log(error);
});
Conn.start().done(function (data) {
//console.log(_SinglaR_News_conn.state);
//console.log(data);
}).fail(function (data) {
//console.log(_SinglaR_News_conn.state);
console.log("start fail:" + data);
});
};
新建实例
var _SinglaR= new mySignalR();
_SinglaR.Hub = "MainHub";//服务端集线器类名
_SinglaR.Url = _SinglaR_Url;
//_SinglaR.QueryString.Language = _Language;//自定义参数_SinglaR.QueryString.xxx
_SinglaR.OnEven.OnMessage = function (data) {//注册客户端方法"OnMessage" 该名字可自定义,服务端调用该名字 OnEven.xx可以定义多个方法
//do...
};
_SinglaR.stateChanged = function () {//鏈接狀態改變事件
//this 當前conn對象
if (this.state == 1) {
console.log("连接成功");
}
};
_SinglaR.Start();//连接
//_SinglaR.SendMessage("");//客戶端發送消息到服務器方法 服务端要有方法“FromClient”