原文:SignalR的另类实现技巧

很久之前发表过一篇名为《通过三个DEMO学会SignalR的三种实现方式》的文章,在那篇文章里面详细介绍了在WEB应用下的常用SignalR实现方法,而今天我们来利用SignalR来实现其它的一些用法,比如:B/S 与 C/S互相通讯,比如:C/S与C/S通讯。

一、B/S 与 C/S互相通讯(ASP.NET 向  Winform  广播消息),先看效果如下:

如上图所示,采用服务端发送消息(指在C#代码发送),然后winform接收消息。

如上图所示,采服客户端(浏览器)JS 代理对象发送消息,然后winform接收消息。

上述示例的实现代码如下:

ASP.NET 服务端代码:

MyHub:

    [HubName("myHub")]public class MyHub : Hub{public static Action<string> SendMsgAction = null;public MyHub(){SendMsgAction = new Action<string>(SendMsg);}private void SendMsg(string msg){Clients.All.RecvMsg(msg);}[HubMethodName("broadcast")]public void Broadcast(string msg){if ("broadcast".Equals(Context.QueryString["identity"])) //只有带有广播者身份才能进行广播消息{SendMsg(msg);}}public override System.Threading.Tasks.Task OnConnected(){return base.OnConnected();}[HubMethodName("testConnect")]public void TestConnect(){System.Diagnostics.Debug.Write("ddd");}}

ASP.NET 页面:(演示就用了服务器控件,以便到服务端进行发送)

        <div>广播消息:<input type="text" id="txtmsg" runat="server"  /><asp:Button ID="Button1" runat="server" OnClick="Button1_Click" Text="服务端发送" /></div>

ASP.NET CS代码:

        protected void Button1_Click(object sender, EventArgs e){if(MyHub.SendMsgAction!=null){MyHub.SendMsgAction("服务端发送消息-" + txtmsg.Value);}}

 在这里特别说明一下,因为MyHub是有连接时才会生成实例,我们无法直接在服务端获取到MyHub的实例,所以采取了在MyHub构造函数时,将SendMsg暴露给静态的 SendMsgAction委托,这样服务端就可以直接通过判断SendMsgAction是否有订阅来决定是否可以发送消息。这是一个取巧的的方式,当然如果大家有更好的方法,欢迎交流。

通过浏览器发送实现方法与之前的文章介绍的相同,这里采用代理模式,ASP.NET页面代码如下:(不作过多介绍)

    <script src="<%=ResolveUrl("~/Scripts/jquery-1.10.2.min.js") %>" type="text/javascript"></script><script src="<%=ResolveUrl("~/Scripts/jquery.signalR-2.2.2.min.js") %>" type="text/javascript"></script><script src="<%=ResolveUrl("~/signalr/hubs") %>" type="text/javascript"></script><div>广播消息:<input type="text" id="txtmsg2"  /><input type="button" id="btnSend" value="客户端发送" /></div><script type="text/javascript">$(function () {var myhub = $.connection.myHub;$.connection.hub.qs = { "identity": "broadcast" };$.connection.hub.start().done(function () {$("#btnSend").click(function () {var msg = $("#txtmsg2").val();myhub.server.broadcast("客户端发送消息-" + msg).done(function () {alert("发送成功!");}).fail(function (e) {alert(e);$("#txtmsg2").focus();});});});});</script>

 这里有一个注意点:我们在定义MyHub类时,按照CSharp的代码规范是:类名 及方法名首字母都大写,但JS自动生成的代理JS类及方法名却会变成JS的命规范,即:函数名首个字母是小写,如:MyHub -->myHub,所以为了便于兼容JS调用,在定义Hub类时,用上HubName及HubMethodName特性,指定统一名称。

winform客户端接收消息步骤:

1.通过NuGet安装SignalR.Client相关组件

2.Winform CS代码:

    public partial class Form1 : Form{private HubConnection connection = null;private IHubProxy hubProxy = null;private System.Threading.SynchronizationContext syncContext = null;public Form1(){InitializeComponent();syncContext = System.Threading.SynchronizationContext.Current;}private  void Form1_Load(object sender, EventArgs e){CreateHubConnection();}/// <summary>/// 创建Hub代理类,并启动/// </summary>private void CreateHubConnection(){connection = new HubConnection("http://localhost:3510/signalr");//SignalR服务端地址hubProxy = connection.CreateHubProxy("MyHub");hubProxy.On<string>("RecvMsg", RecvMsg); //订阅接收消息connection.Start().Wait();}/// <summary>/// 接收SignalR服务端的消息/// </summary>/// <param name="msg"></param>private void RecvMsg(string msg){syncContext.Post((o) => {textBox1.Text += string.Format("{0:yyyy-MM-dd HH:mm:ss}{1}\r\n", DateTime.Now, o);}, msg);}private void Form1_FormClosed(object sender, FormClosedEventArgs e){connection.Dispose();}private void button1_Click(object sender, EventArgs e){hubProxy.Invoke("TestConnect");//调用SignalR服务端的方法}}

 通过上述代码可以看出,与ASP.NET 页面生成的JS代理类的方式原理基本相同,都是通过代理类来与服务端进行交互,都是通过HTTP协议进行通讯。

 二、C/S 与 C/S 互相通讯(winform与winform),其实本质上服务端还是B/S,只不过我们采取了SignalR self Host(里面用到了OWIN self Host),也就是将网站寄宿到winform而矣,只是我们通过winform操作更方更而矣,效果如下:

winform服务端实现流程:

1.先通过NuGet 分别安装Microsoft.AspNet.SignalR、Microsoft.AspNet.SignalR Self Host,如下图示:

2.添加Startup类文件,并在里面添加映射SignalR,代码如下:(与ASP.NET服务端的Startup代码相同)

    public class Startup{public void Configuration(IAppBuilder app){app.MapSignalR();}}

3.编写OWIN 的寄宿代码,MyHub与上文中的相同,故不再贴出

    public partial class Form1 : Form{private IDisposable webHost = null;public static Form1 Current = null;public Form1(){InitializeComponent();this.Text = "SignalR Winform服务端";Current = this;}private void Form1_Load(object sender, EventArgs e){try{webHost = WebApp.Start<Startup>("http://localhost:3512");label2.Text = "http://localhost:3512";}catch (Exception ex){MessageBox.Show(ex.Message);}}private void Form1_FormClosed(object sender, FormClosedEventArgs e){try{webHost.Dispose();}catch{ }}private void button1_Click(object sender, EventArgs e){if(MyHub.SendMsgAction!=null){MyHub.SendMsgAction(textBox1.Text);}}public void ShowMsg(string msg){this.Invoke(new MethodInvoker(() => {listBox1.Items.Add(msg);}));}}

 这里有几个小细节需要注意:

1.安装Microsoft.AspNet.SignalR后会在项目中生成Sciprts文件夹,这个在winform项目时就可以删除掉;

2.安装Microsoft.AspNet.SignalR Self Host后,编译可能无问题,但运行起来时,可能会报朱找到匹配的OWin程序集,这个是因为OWIN版本问题,只需单独再安装一下指定的OWIN版本即可。

SignalR的另类实现技巧相关推荐

  1. keep怎么生成运动轨迹_KEEP的另类使用技巧——旅行记录

    2015年,是夜跑流行起来的一年,也是大学时候怎么也吃不胖的我,开始发胖的一年.作为一个软件测评的重度爱好者,对运动类APP自然也是不能放过.在平行使用过咕咚.KEEP.虎扑.悦跑圈以及国外的一些软件 ...

  2. .hpp文件_文件上传漏洞另类绕过技巧及挖掘案例全汇总

    文件上传漏洞作为获取服务器权限最快的方式,虽然相关资料很多,但很多人对上传校验方式.如何针对性绕过检测.哪种上传和解析的场景会产生危害等还是比较模糊.本文作一些阐述,然后补充一些除了上传webshel ...

  3. 上传绕过php文件改为图片,文件上传漏洞另类绕过技巧及挖掘案例全汇总

    文件上传漏洞作为获取服务器权限最快的方式,虽然相关资料很多,但很多人对上传校验方式.如何针对性绕过检测.哪种上传和解析的场景会产生危害等还是比较模糊.本文作一些阐述,然后补充一些除了上传webshel ...

  4. 关闭jbox的另类小技巧

    关于jbox关闭的一些小技巧 最近这两天写一个项目需要用到jbox,但是关闭始终无法完美解决. 网上提供了很多方法,但是都不适合我,我是一个添加资料的输入页面,想要实现提交成功后自动关闭jbox,不再 ...

  5. Linux命令行另类使用技巧

    0x00 基础简述 0x01 补全实践 bash-completion zsh-autosuggestions 文件名补全 特殊补全 命令行参数补齐 可编程补全 0x02 历史命令 设置历史记录 查看 ...

  6. Outlook另类小技巧 批量处理图片大小

    转换为成体积较小的jpg格式图片 如果你的照片是TIFF.RAW 等非jpg 格式,那么想把它们批量转换成体积较小的jpg格式该如何操作呢? (1)通过单击"开始",然后双击&qu ...

  7. 实用技巧:使用 Google Analytics 跟踪 JS 错误

    Google Analytics(谷歌分析)不仅仅是一个流量统计工具,你还可以用它来测量广告活动的有效性,跟踪用户多远到所需的页面流(从点击广告到购物车到结账页面)获取,并基于用户的信息设置浏览器和语 ...

  8. 年终盘点|知数堂2017年度好文

    因为加班.约会.加班.约会,错过了知数堂无数次的公开课和技术分享~ 早上还在懊恼遗憾,现在又齐齐整整地回来了~ 而幸福就是,这种失而复得的小确幸 这篇文章内涵满满,一年的技术分享都囤这了~ 年关将至, ...

  9. ■■■照片后期处理经典实例教程1500篇■■■

    Photoshop正片叠底模式给钟表变换背景 Photoshop打造MM漂亮透明面板效果 "线性渐变"和"对称渐变,"填充透明度"和"不透明 ...

最新文章

  1. 习题10-2 递归求阶乘和 (15 分)
  2. getconnectiontimeoutexception 网络问题排查_通俗解析居家宽带网络问题:光猫设备排查教程篇...
  3. 七层负载均衡--Haproxy
  4. php框架全局自定义错误,[TP笔记]ThinkPHP自定义错误页面、成功页面及异常页面
  5. 什么才是软件开发的葵花宝典?
  6. javaweb:servlet过滤器
  7. 高额奖金+实习机会+官方证书 丨微众银行第二届金融科技高校技术大赛正式启动...
  8. 【NetApp】NetBoot的使用方法
  9. 使用面向对象(OO)的思想,实现循环输入多个会员的信息,根据会员编号,查找会员积分
  10. 《信息检索导论》第七章总结
  11. LintCode MySQL 1921. 从不充值的玩家(where not in)
  12. mysql explain key为空_MySQL中explain的使用以及性能分析
  13. CodeForces 598A Tricky Sum
  14. java for语句(翻译自Java Tutorials)
  15. javascript删除数组某个元素
  16. Ubuntu Kvm USB重定向问题解决
  17. 开源播放器内核比较:ijkPlayer、VLC、ExoPlayer、MediaPlayer、SmartPlayer
  18. PSNRSSIMVIF指标-python版本
  19. 小程序推广换量经验分享
  20. 【vite+pinia】

热门文章

  1. 【转】OpenStack和Docker、ServerLess能不能决定云计算胜负吗?
  2. 配置scp在Linux或Unix之间传输文件无需密码
  3. 创建sql自定义的函数及商品分页sql存储过程
  4. Java 多线程 之 银行ATM实例
  5. Android备份和添加短信
  6. 从Facebook看大数据存储怎么选
  7. Python 字符串的所有方法详解
  8. 不得不提的团队协作工具
  9. 【直播预告】云栖直播:阿里热修复产品HotFix2.0升级详解
  10. Mac系统Git生成ssh公钥