c#如何实现显示在线用户列表的功能

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了c#如何实现显示在线用户列表的功能相关的知识,希望对你有一定的参考价值。

在ASP时代,要实现一个网站的在线用户列表显示功能的惯用做法是修改global.asa文件中的:Application_Start、Session_Start和Session_End这三个函数。在ASP.NET时代,我依然这样做。但是必须注意很多问题。首先来看看最简单的代码实现:

protected void Application_Start(Object sender, EventArgs e)

Application.Lock();

Application["OnlineUsers"]=null;

Application.UnLock();


protected void Session_Start(Object sender, EventArgs e)

Application.Lock();

if(Application["OnlineUsers"]==null)
Application["OnlineUsers"]=new Hashtable();

Hashtable onlineUsersHash=(Hashtable)Application["OnlineUsers"];
onlineUsersHash.Add(Request.UserHostAddress, Request.Cookies["UserName"].Value);

Application.UnLock();


protected void Session_End(Object sender, EventArgs e)

Hashtable onlineUsersHash=(Hashtable)Application["OnlineUsers"];
onlineUsersHash.Remove(Request.UserHostAddress);


这就是一个简单的能实现记录在线用户列表的代码。呵呵,简单吧?你可以传到服务器上去试试!如果你和我一样,看到自己的用户名已经出现在列表中,就欢呼雀跃地告诉许多网友很简单就实现了一个在线用户列表显示功能,然后就关了机器去睡觉了的话,那么第二天清晨你会大吃一惊!你的网站上的在线用户列表中的人名会多的数不清,而且你会知道其实那些人根本就不在线上… 哦,真是个灾难!算法思想没有任何错误,但是却得出错误的结果,为什么呢?虽然是一个小小的功能,但是却隐藏了许多玄机,这个就要看你是否能解开了…
首先我要肯定一点,用Hashtable这样的数据结构来存储在线用户的名称的确是个不错的选择。主键使用用户的IP地址,主键值存放用户名称。因为网络中的IP地址是唯一的,所以用它来充当主键时对的。出现上述错误的原因是在Session_End函数中,Hashtable没有将主键删除掉?!
我想所有初学者都会和我一样,会问:既然IP地址在整个网络中是唯一的,那为什么还无法删除Hashtable中的键呢?答案是:Hashtable没有找到主键名,即用户的IP地址:Request.UserHostAddress!这听起来真是笑话,用户IP地址怎么会找不到呢?只要用户登陆Internet,就必有IP地址!它怎么会找不到呢?
我告诉你,原因是:用户根本就没有登陆Internet!
什么在线,又不在线的?我想你现在应该已经晕了… 不过,看了下面的图例,我想你就明白了…
如果觉得示意图有些小,可以调整显示比例(Word菜单 à 视图 à 显示比例)。

左图是假设一个用户先登录Bincess论坛,而后就去了WadeLau.org(WadeLau.net)这个网站。但是他一直没有断开连接,一直都在Internet上。而当AfritXia.net的服务器结束了用户的Session时,就会调用:

protected void Session_End(Object sender, EventArgs e)

Hashtable onlineUsersHash=(Hashtable)Application["OnlineUsers"];
onlineUsersHash.Remove(Request.UserHostAddress);
追问

亲们,不要随便copy了。来点实际的

追答

楼下的回答的就可以,用session也行啊

参考技术A 我觉得LZ问的不只是代码方便的.
首先设计的时候你得给用户加一个标志位,比如是在数据库中用户的属性有一条是ONLINE,当字段为1,则为在线,为0,离线.
所以需要显示在线功能的时候只需要一个存储过程,从数据库中读取出Online的标志位为1的即可追问

什么时候修改online状态呢?比如登陆成功了可以修改为1,当直接关闭网页,或者session失效了又该怎么处理呢?

追答

好细心的LZ,呵呵.
你可以写一个函数,比如每10分钟查次用户是否真实存在,很多网站都是这样做的,也就是为什么下线了会有延迟在线的显示

本回答被提问者采纳

Android with Smack - 如何获取在线用户列表?

【中文标题】Android with Smack - 如何获取在线用户列表?【英文标题】:Android with Smack -How to get list of online users? 【发布时间】:2016-12-12 10:15:46 【问题描述】:

我正在使用 jivesoftware Smack SDK 来实现实时聊天功能。 为了创建连接,我使用以下代码,

XMPPTCPConnectionConfiguration.Builder config = XMPPTCPConnectionConfiguration.builder();
    config.setSecurityMode(ConnectionConfiguration.SecurityMode.disabled);

    config.setServiceName("world-pc");
    config.setHost(serverAddress);
    config.setPort(5222);
    config.setDebuggerEnabled(true);
    XMPPTCPConnection.setUseStreamManagementResumptiodDefault(true);
    XMPPTCPConnection.setUseStreamManagementDefault(true);
    connection = new XMPPTCPConnection(config.build());
    XMPPConnectionListener connectionListener = new XMPPConnectionListener();
    connection.addConnectionListener(connectionListener);
    connection.connect();
    connection.login("username","password");

而且它工作得非常好。 现在的事情是,我想获取特定用户的在线状态或获取所有在线用户的列表。 我已经尝试了许多堆栈溢出的解决方案,但对我来说没有任何效果。 我尝试过的解决方案之一是,

Presence presence = new Presence(Presence.Type.available);
connection.sendPacket(presence);
Roster roster = xmppConnection.getRoster();
Collection<RosterEntry> entries = roster.getEntries();
Presence presence;

for(RosterEntry entry : entries) 
presence = roster.getPresence(entry.getUser());

System.out.println(entry.getUser());
System.out.println(presence.getType().name());
System.out.println(presence.getStatus());
 

这会返回一个列表,但所有用户的状态都是空的。 请有人帮我提供准确的解决方案。

谢谢

【问题讨论】:

您的客户发送 Presence 吗? 是的..请检查已编辑的问题 【参考方案1】:

您可以使用Presence.Type.subscribe 来了解(作为用户)另一个用户的状态:

Presence subscribe = new Presence(Presence.Type.subscribe);
subscribe.setTo('another_user@example.com');
connection.sendPacket(subscribe);

“another_user”应该以同样的方式批准您的请求:

Presence subscribe = new Presence(Presence.Type.subscribe);
subscribe.setTo('another_user@example.com');
connection.sendPacket(subscribe);

【讨论】:

好的,有没有监听用户状态变化的监听器? @Jay Vyas 尝试 RosterListener【参考方案2】:

Presence 它由 TYPE(如:Presence.Type.availablePresence.Type.unavailable)和来自用户的自定义可空 status(如“Hello World!”或“今天我很开心”或“工作中”现在”)。

要设置状态,只需在发送前设置:

Presence presence = new Presence(Presence.Type.available);
presence.setStatus("Online and ready to chat");
connection.sendStanza(presence); //or old one: connection.sendPacket(presence)

【讨论】:

我不想设置我的状态..我想要其他用户的状态,我没有找到任何像“sendStanza”这样的连接对象方法 每个用户只能设置自己的“状态”,所以基本上如果所有人都设置自己的状态,您将能够将其作为不为空的字符串来获取。当然,您必须管理 null 作为 getStatus 的可能性(检查并设置为“”)。如果您没有找到任何“connection.sendStanza()”方法,只需使用旧的“sendPacket”,您使用的是旧版本的 SMACK。 好吧,让我按照你的建议试试 我再次阅读了您的问题,可能有一个很大的误导:在 Openfire(或任何服务器)中,“状态”意味着“已连接 || 已断开 || foo”到服务器。客户端,“状态”它被映射并用 Presence 屏蔽,这是一个允许任何用户向他人屏蔽自己的系统(例如:Skype 的不可见)、可用(和在线)、请勿打扰(和在线)等等。用户在服务器在线时可能不可用(对于允许通过名册检查可用性的其他用户)。此外,Presence 有一个“状态”,它就像 Skype 的个人消息一样只是一条消息。服务器状态对客户端不可见 状态意义上的,我想在发送他/她的消息之前检查用户是否与开火服务器连接

以上是关于c#如何实现显示在线用户列表的功能的主要内容,如果未能解决你的问题,请参考以下文章

在线/离线用户功能 Firestore 或实时的更好解决方案是啥?

C#如何实现视频在线播放

XMPPFramework - 如何获取在线和离线好友列表?

技术分享| 基于RTM 实现的呼叫邀请如何添加推送功能?

API调用Netty长链接执行发送消息(在线数用户列表)

如何在 ejabberd/XMPP 中获取所有在线用户的列表?