很久之前发表过一篇名为《通过三个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:
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是否有订阅来决定是否可以发送消息。这是一个取巧的的方式,当然如果大家有更好的方法,欢迎交流。
通过浏览器发送实现方法与之前的文章介绍的相同,这里采用代理模式,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版本即可。
本文转自 梦在旅途 博客园博客,原文链接:http://www.cnblogs.com/zuowj/p/7390791.html ,如需转载请自行联系原作者