原文:WPF+SignalR实现用户列表实时刷新

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/lordwish/article/details/51789884

在实时通信应用中,最常用也最基本的就是终端列表的实时刷新,也就是当客户端上线或下线时,服务端都会向全体客户端推送通知及新的在线客户端列表。


客户端类

    public partial class ClientModel
{
public ClientModel()
{
}
private string _client_name;
private string _client_ip="192.168.1.1";
private string _connectionid;
//计算机名
public string ClientName
{
set { _client_name = value; }
get { return _client_name; }
}
//计算机IP
public string ClientIP
{
set { _client_ip = value; }
get { return _client_ip; }
}
//通信连接id
public string ConnectionId
{
set { _connectionid = value; }
get { return _connectionid; }
}
}

服务端

服务端创建

服务端创建请参考下面文章

[使用WPF创建SignalR服务端]

服务端方法

在MyHub类中添加服务端方法。对于客户端上线建立连接,服务端方法有两种,一种是重载Hub类的OnConnected方法,另一种是就是自定义的方法了。OnConnected方法在客户端与服务端建立通信连接时会被立即调用,但我们很多时候是先建立连接等到用户验证后再登录刷新在线终端列表,也就是说两者的触发时机不同,但基本原理是一致的。

首先定义一个变量来存储在线终端信息:

public List<ClientModel> ClientList = new List<ClientModel>();

OnConnected方法

        public override Task OnConnected()
{
ClientModel client = new ClientModel
{
ClientName = GetName(),//获取远程计算机名
ClientIP = GetIp(),//获取远程计算机IP
ConnectionId=Context.ConnectionId
};
foreach (ClientModel m in ClientList)
{
if (m.ClientIp==client.ClientIp)
{
ClientList.Remove(m);
break;
}
}
ClientList.Add(client);
Clients.All.getclientlist(ClientList);
string output = string.Format("用户 {0} 上线,IP:{1}", client.ClientName, client.ClientIP);
Application.Current.Dispatcher.Invoke(() =>
{
((MainWindow)Application.Current.MainWindow).WriteToConsole(output);
});
return base.OnConnected();
}

自定义方法GetClientList

public Task GetClientList(string clientname,string clientmac,string clientip)
{
ClientModel client = new ClientModel
{
ClientName = clientname,
ClientIP = clientip,
ConnectionId=Context.ConnectionId
};
foreach (Model.ClientModel m in ClientList)
{
if (m.ClientIp==clientip)
{
ClientList.Remove(m);
break;
}
}
ClientList.Add(client);
Task all = Clients.All.getclientlist(ClientList);
string output = string.Format("用户 {0} 上线,IP:{1}", client.ClientName, client.ClientIP);
Application.Current.Dispatcher.Invoke(() =>
{
((MainWindow)Application.Current.MainWindow).WriteToConsole(output);
});
return all;
}

客户端

创建WPF项目ClientApp(不低于.NET Framework 4.0),使用NuGet管理器引用SignalR程序包,只需要引用Microsoft.AspNet.SignalR.Client即可。使用设计器添加一个数据列表(DataGrid或ListView)用于绑定在线客户端列表。

创建并启动通信连接

    public static HubConnection Connection = new HubConnection(ConfigurationManager.AppSettings["ServiceUri"]);
public static IHubProxy MyHub; public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
ConnectAsync();
} private async void ConnectAsync()
{
MyHub = Connection.CreateHubProxy("MyHub");
try
{
await Connection.Start();//建立连接
}
catch (Exception)
{
throw;
}
}

针对服务端的实现方法,客户端也有不同的方法,如果使用服务端的OnConnected方法,上面的方法足够了,因为客户端的基本信息都是包含在Context中的,客户端与服务端建立连接时,服务端可以从Context中获取客户端信息。当然也可以写个自定义方法连接服务端的GetClientList方法。

private void ClientOnline()
{
string clientname=GetName();
string clientip=GetIP();
MyHub.Invoke("",clientname,clientip);
}

在通信连接建立后或在用户执行相应操作后执行此方法,向服务端发送客户端信息,服务端经过处理后将更改后的在线客户端列表广播至各客户端,现在缺少的就是客户端监听服务端的方法了。监听方法本质是一个长轮询,可以在其中接受服务端推送的数据并执行相应操作。

public MainWindow()
{
InitializeComponent();
ConnectAsync();
ConnectListener();
}
public void ConnectListener()
{
MyHub.On<List<ClientModel>>("getclientlist", list =>{
//数据绑定
this.Dispatcher.Invoke(delegate{
dgList.ItemsSource = list;
})
});
}

最后就需要关闭终端下线的方法了

服务端:

        public override Task OnDisconnected(bool stopCalled)
{
Model.ClientModel client = new Model.ClientModel();
foreach (Model.ClientModel m in ClientList)
{
if (m.ConnectionId==Context.ConnectionId)
{
client = m;
ClientList.Remove(m);
break;
}
}
Clients.All.getuserlist(ClientList);
string output = string.Format("用户 {0} 下线,IP:{1}", client.ClientName, client.ClientIP);
Application.Current.Dispatcher.Invoke(() =>
{
((MainWindow)Application.Current.MainWindow).WriteToConsole(output);
});
return base.OnDisconnected(stopCalled);
}

客户端

        private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
Connection.Stop();
Connection.Dispose();
}

其实上面只是简单的示例,而实际的业务场景会更复杂,但其基本原理是一致的,多多思考,可以扩展更多。

WPF+SignalR实现用户列表实时刷新的更多相关文章

  1. 使用SignalR实现比特币价格实时刷新

    ASP.NET SignalR是微软支持的一个运行在 Dot NET 平台上的 HTML Websocket 框架.它出现的主要目的是实现服务器主动推送(Push)消息到客户端页面,这样客户端就不必重 ...

  2. C#开发微信门户及应用(4)--关注用户列表及详细信息管理

    在上个月的对C#开发微信门户及应用做了介绍,写过了几篇的随笔进行分享,由于时间关系,间隔了一段时间没有继续写这个系列的博客了,并不是对这个方面停止了研究,而是继续深入探索这方面的技术,为了更好的应用起 ...

  3. 使用SignalR+Asp.net创建实时聊天应用程序

    一.概述: 使用 ASP.NET 那么 SignalR 2 创建一个实时聊天应用程序.将 SignalR 添加 MVC 5 应用程序中,并创建聊天视图发送并显示消息. 在Demo中,将学习Signal ...

  4. 基于Redis的在线用户列表解决方案

    前言: 由于项目需求,需要在集群环境下实现在线用户列表的功能,并依靠在线列表实现用户单一登陆(同一账户只能一处登陆)功能: 在单机环境下,在线列表的实现方案可以采用SessionListener来完成 ...

  5. [项目回顾]基于Redis的在线用户列表解决方案

    迁移:基于Redis的在线用户列表解决方案 前言: 由于项目需求,需要在集群环境下实现在线用户列表的功能,并依靠在线列表实现用户单一登陆(同一账户只能一处登陆)功能: 在单机环境下,在线列表的实现方案 ...

  6. SignalR指定用户推送消息

    一.首先,在MVC项目中安装SingalR包(SingalR2.0需要.net4.5以上,VS2010可以安装1.1.3版本,本例为VS2010+SignalR1.1.3). 打开工具-NuGet程序 ...

  7. 【Java框架型项目从入门到装逼】第十四节 查询用户列表展现到页面

    这一节,我们来实现一下用户列表搜索,最终的效果如下: 这边我们要使用easyUI给我们提供的datagrid组件. HTML结构如下 <!-- 数据列表 --> <table id= ...

  8. Vue+WebSocket 实现页面实时刷新长连接

    最近vue项目要做数据实时刷新,折线图每秒重画一次,数据每0.5秒刷新一次,说白了就是实时刷新,因为数据量较大,用定时器估计页面停留一会就会卡死... 与后台人员讨论过后决定使用h5新增的WebSoc ...

  9. gulp使用 实现文件修改实时刷新

    gulp例子:https://github.com/Aquarius1993/gulpDemo 淘宝镜像:$ npm install -g cnpm --registry=https://regist ...

随机推荐

  1. js取对象的属性值循环

    var data = {name: "liuyang", job: "web", age: "27"} Object.keys(data). ...

  2. 【2017 Multi-University Training Contest - Team 10】Schedule

    [链接]http://acm.hdu.edu.cn/contests/contest_showproblem.php?pid=1010&cid=767 [题意] 给一些区间,每台机器在这些区间 ...

  3. [React & Debug] Quick way to debug Stateless component

    For example we have the following code: const TodoList = (props) => ( <div className="Tod ...

  4. Codeforces Round #445 Div. 1 C Maximum Element (dp + 组合数学)

    题目链接: http://codeforces.com/contest/889/problem/C 题意: 给你 \(n\)和 \(k\). 让你找一种全排列长度为\(n\)的 \(p\),满足存在下 ...

  5. Node知识总结

    一. 伪装URL-SEO 伪URL重写 把一个动态页面的地址重写为静态页面的地址,为了方便网站的SEO优化 真实地址:http://item.jd.com/detail.php?id=12261336 ...

  6. 使用mybatis generator 生成annotation形式的mapper

    最近使用mybatisgenerator时,希望生成annotation的mapper,在网上基本桑没有相关配置,记录,做以下记录: <?xml version="1.0"  ...

  7. linux下设置密码复杂度限制,怎么设置?

    在linux,设置密码复杂度的方法有几个1. 一个是在/etc/login.defs文件,里面几个选项PASS_MAX_DAYS 90 #密码最长过期天数PASS_MIN_DAYS 80 #密码最小过 ...

  8. 5W1H分析法和5W2H分析法

    5W1H分析法也称六何分析法,是一种思考方法,也可以说是一种创造技法.是对选定的项目.工序或操作,都要从原因(WHY).对象(WHAT).地点(WHERE).时间(WHEN).人员(WHO).方法(H ...

  9. Oracle-18-select语句初步&amp;SQL中用算术表达式&amp;别名的使用&amp;连接运算符%distinct&amp;where子句

    一.一般SELECT语句的格式例如以下: 1.查询指定表的全部列 select * from 表名 [where 条件] [group by 分组列名] [having 聚合函数] [order by ...

  10. HDU 1405 The Last Practice 数学水题

    http://acm.hdu.edu.cn/showproblem.php?pid=1405 题目大意: 给你一个数,让你分解素因子,输出它的各次幂. 如60 输出:2 2 3 1 5 1 (60=2 ...