最近在做一个项目,需要用到服务端主动推送给客户端,最开始用的是自己比较顺手的Remoting,可后来发现把服务端架到外网上,就猴子它哥了,后来又尝试WCF,虽然能推送,但是推了几次也猴子它哥了,后来找到了SignalR,关于这个通讯框架的资料,自己去查查,很方便的,但是关于winform这方面的资料特别少,全是web的,以免大家重蹈覆辙,所以就写下这篇文章。
服务端代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNet.SignalR;
namespace SignalRServer
{
public class BroadcastContext
{
//单例模式 所有客户端都共用此实例 才能达到广播的效果
private static readonly BroadcastContext instance =
new BroadcastContext(GlobalHost.ConnectionManager.GetHubContext<BroadcastHub>());
private readonly IHubContext context;
//功能业务类
private readonly FunctionApp functionApp;
public static BroadcastContext Instance
{
get { return instance; }
}
private BroadcastContext(IHubContext context)
{
this.context = context;
functionApp = new FunctionApp(context);
functionApp.Action();
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNet.SignalR;
namespace SignalRServer
{
public class BroadcastHub : Hub
{
private readonly BroadcastContext broadcastContext;
public BroadcastHub()
{
broadcastContext = BroadcastContext.Instance;
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Owin.Cors;
using Owin;
namespace SignalRServer
{
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.UseCors(CorsOptions.AllowAll);
app.MapSignalR();
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNet.SignalR;
using System.Threading;
namespace SignalRServer
{
public class FunctionApp
{
//上下文
private readonly IHubContext context;
public FunctionApp(IHubContext context)
{
this.context = context;
}
string[] actons = {"6:30 起床了","7:00 做广播体操","7:30 吃早餐","8:00 该干嘛干嘛" };
Random r = new Random();
public void Action()
{
//测试广播功能
Task.Run(() => Start());
}
private void Start()
{
while (true)
{
Thread.Sleep(500);
//客户端调用的方法名必须一致
context.Clients.All.ReceiveMsg("ClientId=>"+r.Next(1,20),"Message=>"+actons[r.Next(0, 4)]);
}
}
}
}
using Microsoft.Owin.Hosting;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace SignalRServer
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
string url = "http://192.168.1.77:8086";
private void Form1_Load(object sender, EventArgs e)
{
WebApp.Start<Startup>(url);
lblInfo.Text = "服务启动成功";
}
}
}
客户端代码:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Microsoft.AspNet.SignalR.Client;
namespace SignalRClient
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
HubConnection connection = null;
IHubProxy myHub = null;
string url = "http://192.168.1.77:8086";
private void Form1_Load(object sender, EventArgs e)
{
connection = new HubConnection(url);
//类名必须与服务端一致
myHub = connection.CreateHubProxy("BroadcastHub");
//方法名必须与服务端一致
myHub.On<string, string>("ReceiveMsg", ReceiveMsg);
connection.Start().ContinueWith(task =>
{
if (!task.IsFaulted)
{
richTextBox1.Text = "与服务器连接成功!\r\n";
}
else
{
richTextBox1.Text = "与服务器连接失败,请确认服务器是否开启!\r\n";
}
}).Wait();
}
private void ReceiveMsg(string clientId,string message)
{
richTextBox1.Text += clientId+" "+ message+ "\r\n";
}
}
}
完整代码下载链接