使用windows服务、SignalR实现双工通讯之客户端篇

上一篇文章实现了用windows服务为宿主的SignalR通讯服务端,这一篇将实现用windows服务为宿主的通讯客户端。

废话不多说,放码上来。。。

1、新建一个类库,封装SignalR的客户端相关方法,代码如下:

  1 public class SignalRClient
  2     {
  3         //与服务端的交互
  4 
  5         /// <summary>
  6         /// SignalR通讯管道
  7         /// </summary>
  8         private IHubProxy HubProxy { get; set; }
  9         /// <summary>
 10         /// SignalR通讯服务端地址
 11         /// </summary>
 12         private string ServerURI;
 13         /// <summary>
 14         /// SignalR通讯管道名称
 15         /// </summary>
 16         private string HubName;
 17         /// <summary>
 18         /// 当前客户端
 19         /// </summary>
 20         private ClientInfo Client;
 21         private Logger Log = new Logger(LogName.Signalr_Client.ToString());
 22         /// <summary>
 23         /// 错误信息备注
 24         /// </summary>
 25         private string ErrMsgRemark = "";
 26         private JsonSerializerSettings JsonSetting;
 27 
 28         public SignalRClient(string url,string port,string hubName)
 29         {
 30             //获取到客户端传来的客户端信息
 31             JsonSetting = new JsonSerializerSettings();
 32             JsonSetting.NullValueHandling = NullValueHandling.Ignore;
 33             this.HubName = hubName;
 34             this.ServerURI = "http://" + url + ":" + port + "/signalr";
 35         }
 36         private HubConnection SrConnection { get; set; }
 37      
 38         private void RegisterHunFun()
 39         {
 40             //定义客户端开机设置
 41             ErrMsgRemark = "注册Sr通讯管道客户端函数异常!";
 42             try
 43             {
 44                 HubProxy.On(ClientHubFunName.TestClient.ToString(), () =>
 45                 {
 46                     SrClientHandl.TestClient();
 47                 });
 48                 HubProxy.On<ClientInfo>(ClientHubFunName.BootSetting.ToString(), (ClientInfo client) =>
 49                  {
 50                      SrClientHandl.BootSetting(client);
 51                  });
 52                 HubProxy.On<ClientInfo>(ClientHubFunName.ShutdownSetting.ToString(), (ClientInfo client) =>
 53                 {
 54                     SrClientHandl.ShutdownSetting(client);
 55                 });
 56                 HubProxy.On<ClientInfo>(ClientHubFunName.GetFlowInfo.ToString(), (ClientInfo client) =>
 57                 {
 58                     SrClientHandl.GetFlowInfo(client);
 59                 });
 60                 HubProxy.On<ClientInfo>(ClientHubFunName.LogTrans.ToString(), (ClientInfo client) =>
 61                 {
 62                     SrClientHandl.LogTrans(client);
 63                 });
 64                 HubProxy.On<ClientInfo>(ClientHubFunName.PerfectClientAttribute.ToString(), (ClientInfo client) =>
 65                 {
 66                     this.Client = client;
 67                 });
 68             }
 69             catch (Exception ea)
 70             {
 71                 Log.Error(ErrMsgRemark, ea);
 72                 throw ea;
 73             }
 74         }
 75 
 76         private ClientInfo GetCurrentClient()
 77         {
 78             Client = new ClientInfo();
 79             Client.ClientId = "1111"; 
 80             return Client;
 81         }
 82         //客户端连接
 83         public async void ConnectAsync() //
 84         { 
 85             Log.Info("进入方法Connect,HubName:" + HubName);
 86             try
 87             {
 88 
 89                 //传给服务端本机信息
 90                 string clientJson = JsonConvert.SerializeObject(GetCurrentClient(), JsonSetting);
 91                 Log.Info("进入方法Connect,传输的客户端json:" + clientJson);         
 92                 var querystringData = new Dictionary<string, string>();
 93                 querystringData.Add("ClientJson", clientJson);
 94                 SrConnection = new HubConnection(ServerURI, querystringData);
 95     
 96                 SrConnection.Closed += Connection_Closed;
 97                 HubProxy = SrConnection.CreateHubProxy(this.HubName);
 98     
 99                 Log.Info("进入方法Connect1");
100                 RegisterHunFun();
101                 try
102                 {
103                     await SrConnection.Start();
104                 }
105                 catch (Exception ea)
106                 {
107                     Log.Error("开启SR链接异常!", ea);
108                 }
109              
110                 //调用服务端方法
111                 Log.Info("调用服务端方法SendTest");
112                 await HubProxy.Invoke("SendTest", "测试");
113                 Log.Info("链接服务端完毕");
114             }
115             catch (Exception ea)
116             {
117                 /*这里异常会有一个隐性问题,如客户端未启动起来就悲剧了
118                  最好办法是加一个定时服务,检测与服务端通信是否打开,未打开就再次开启链接
119                  */
120                 Log.Error(ea);
121             }
122 
123         }
124         //客户端关闭事件
125         private void Connection_Closed()
126         {
127             //通知服务端下线
128 
129             if (SrConnection != null)
130             {
131                 SrConnection.Stop();
132                 SrConnection.Dispose();
133             }
134         }
135     }
View Code

上面SrClientHandl类就是封装RegisterHunFun方法里调用的方法,因为有具体工作的相关代码,这里就不上代码了

2、新建windows服务作为客户SignalR宿主,具体代码如下:

1   string srUrl = SignalRContext.Current.ServerIpAddress;
2                 string srPort = SignalRContext.Current.ServerPort;
3                 string srHub = SignalRContext.Current.HubName;
4                 log.Info("srUrl:" + srUrl + ",srPort:" + srPort + ",srHub:" + srHub);
5                 SignalRClient srClient = new SignalRClient(srUrl, srPort, srHub);
6                 log.Info("开始连接服务端");
7                 srClient.ConnectAsync();
8                 log.Info("连接服务端成功");
View Code

3、再补充下,客户端调用服务端方法还是服务端调用客户端开放的方法,双方都可以得到对方方法的返回值的。

这是我服务端的方法:

 1  //测试数据传输方法
 2         public ClientInfo SendTest(string name)
 3         {
 4             Log.Info("客户端执行服务端方法,参数name:" + name);
 5             Log.Info(" Context.ConnectionId:" + Context.ConnectionId);
 6             ClientInfo info = new ClientInfo();
 7             info.ClientName = name;
 8             info.ConnId = Context.ConnectionId;
 9             return info;
10         }
View Code

这是我客户端调用服务端方法的片段:

1   await SrConnection.Start();//开启链接
2                 //调用服务端方法
3                 Log.Info("调用服务端方法SendTest");
4                 ClientInfo cl = await SrClientHandl.InvokeServerFunAsync<ClientInfo>(ServerHubFunName.SendTest, HubProxy, new object[] { "test" });
5                 Log.Info("得到服务端返回的clientinfo:" + JsonConvert.SerializeObject(cl, JsonSetting));
View Code

SrClientHandl.InvokeServerFunAsync方法是我封装的一个客户端调用服务端异步方法,代码如下

1   //异步执行有返回值的服务端方法 
2         public async static Task<T> InvokeServerFunAsync<T>(ServerHubFunName fun, IHubProxy hub, params object[] args)
3         {
4             T result = await hub.Invoke<T>(fun.ToString(), args);
5             return result;
6         }
View Code

这是日志效果:

 

暂时还不知道怎么查看当前的SignalR使用的哪种通讯方式,因为客户端不是浏览器,应该不是websocket,如果是长连接不知道实际效率怎么样。。。 有SignalR经验丰富的小伙伴可以和我互动下,一起加油!

至此一切ok了。。。。

安利一下微软提供的Signalr相关页面,有兴趣的可以看下:

https://www.asp.net/signalr/overview/getting-started/introduction-to-signalr

 

posted @ 2017-01-13 21:51  长沙大鹏  阅读(459)  评论(0编辑  收藏  举报