SignalR的交互技巧

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

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

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

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

ASP.NET 服务端代码:

MyHub:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
[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 页面:(演示就用了服务器控件,以便到服务端进行发送)

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

ASP.NET CS代码:

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

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

扫描二维码关注公众号,回复: 2152177 查看本文章

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
< 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代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
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代码相同)

1
2
3
4
5
6
7
public  class  Startup
{
     public  void  Configuration(IAppBuilder app)
     {
         app.MapSignalR();
     }
}

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
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版本即可。

猜你喜欢

转载自blog.csdn.net/u011966339/article/details/79930622