/// <summary> /// 用户基础类 /// </summary> public class OnlineUser { #region 私有字段 private string id; private string name = "游客"; private DateTime startTime = DateTime.Now; private DateTime lastTime = DateTime.Now; private string lastIP; private bool isUser = false; private string lastUrl; #endregion #region 公共属性 /// <summary> /// 获取或设置用户名 /// </summary> public string Name { get { return name; } set { name = value; } } /// <summary> /// 获取或设置ID /// </summary> public string ID { get { return id; } set { id = value; } } /// <summary> /// 获取或设置开始访问时间 /// </summary> public DateTime StartTime { get { return startTime; } set { startTime = value; } } /// <summary> /// 获取或设置最后访问时间 /// </summary> public DateTime LastTime { get { return lastTime; } set { lastTime = value; } } /// <summary> /// 获取或设置是否会员(True会员False游客) /// </summary> public bool IsUser { get { return isUser; } set { isUser = value; } } /// <summary> /// 获取或设置用户IP /// </summary> public string LastIP { get { return lastIP; } set { lastIP = value; } } /// <summary> /// 获取或设置最后请求网址 /// </summary> public string LastUrl { get { return lastUrl; } set { lastUrl = value; } } /// <summary> /// 获取在线时间(秒) /// </summary> public double OnlineSeconds { get { return (lastTime - startTime).TotalSeconds; } } #endregion } /// <summary> /// 用户在线类 /// </summary> /// <typeparam name="string">Key</typeparam> /// <typeparam name="OnlineUser">值</typeparam> public class CacheOnline { #region 私有字段 private static CacheOnline instance; private static readonly object syncRoot = new object(); //会员列表 private Dictionary<string, LinkedListNode<OnlineUser>> userList; //所有人数列表 private Dictionary<string, LinkedListNode<OnlineUser>> allUserList; //所有会员列表排序 private LinkedList<OnlineUser> _OnlineUserLink; /// <summary> /// Cache锁 /// </summary> protected ReaderWriterLock readerWriterLock = new ReaderWriterLock(); //定时器 private System.Timers.Timer _UpdateTimer; //登陆超时时间(毫秒) private int timeOut=1000 * 60 * 30; #endregion #region 构造函数 /// <summary> /// 构造函数 /// </summary> private CacheOnline() { userList = new Dictionary<string, LinkedListNode<OnlineUser>>(); allUserList = new Dictionary<string, LinkedListNode<OnlineUser>>(); _OnlineUserLink = new LinkedList<OnlineUser>(); _UpdateTimer = new System.Timers.Timer(); _UpdateTimer.AutoReset = true; _UpdateTimer.Elapsed += new System.Timers.ElapsedEventHandler(ClearTimeOutUser); _UpdateTimer.Interval = timeOut; _UpdateTimer.Start(); } #endregion #region 公共属性 /// <summary> /// 获取所有用户总数 /// </summary> public int AllCount { get { return allUserList.Count; } } /// <summary> /// 获取会员总数 /// </summary> public int MemberCount { get { return userList.Count; } } /// <summary> /// 获取或设置登陆超时时间(毫秒) /// </summary> public int TimeOut { get { return timeOut; } set { timeOut=value; } } /// <summary> /// 获取一个对象实例,该对象在整个运用程序中唯一 /// </summary> /// <returns></returns> public static CacheOnline GetInstance() { if (instance == null) { lock (syncRoot) { if (instance == null) { instance = new CacheOnline(); } } } return instance; } #endregion #region 公共方法 /// <summary> /// 插入用户 /// </summary> /// <param name="onlineUser">用户</param> public void Add(OnlineUser onlineUser) { LinkedListNode<OnlineUser> listNode = new LinkedListNode<OnlineUser>(onlineUser); try { readerWriterLock.AcquireWriterLock(Timeout.Infinite); if (allUserList.ContainsKey(onlineUser.ID)) { ReNewUser(listNode); } else { if (onlineUser.IsUser) { if (!userList.ContainsKey(onlineUser.ID)) { userList.Add(onlineUser.ID, listNode); allUserList.Add(onlineUser.ID, listNode); ReNewUser(listNode); } else { ReNewUser(listNode); } } else { allUserList.Add(onlineUser.ID, listNode); ReNewUser(listNode); } } } finally { readerWriterLock.ReleaseWriterLock(); } } /// <summary> /// 更新用户请求信息 /// </summary> /// <param name="id">id</param> public void Update(string id) { LinkedListNode<OnlineUser> OutNodeUser; try { readerWriterLock.AcquireWriterLock(Timeout.Infinite); if (allUserList.TryGetValue(id, out OutNodeUser)) { ReNewUser(OutNodeUser); } } finally { readerWriterLock.ReleaseWriterLock(); } } /// <summary> /// 访问请求 /// </summary> /// <param name="id">id</param> /// <param name="url">url</param> public void Update(string id, string url) { LinkedListNode<OnlineUser> OutNodeUser; try { readerWriterLock.AcquireWriterLock(Timeout.Infinite); if (allUserList.TryGetValue(id, out OutNodeUser)) { ReNewUser(OutNodeUser, url); } } finally { readerWriterLock.ReleaseWriterLock(); } } /// <summary> /// 根据id移除用户 /// </summary> /// <param name="id">id</param> public void Remove(string id) { LinkedListNode<OnlineUser> UserNode; try { readerWriterLock.AcquireWriterLock(Timeout.Infinite); if (allUserList.TryGetValue(id, out UserNode)) { Remove(UserNode); } } finally { readerWriterLock.ReleaseWriterLock(); } } /// <summary> /// 移除用户资料 /// </summary> /// <param name="UserNode"></param> private void Remove(LinkedListNode<OnlineUser> UserNode) { if (UserNode.List != null) { allUserList.Remove(UserNode.Value.ID); if (UserNode.Value.IsUser) userList.Remove(UserNode.Value.ID); UserNode.List.Remove(UserNode); } } /// <summary> /// 获取在线用户列表 /// </summary> public IList<OnlineUser> GetOnlineUsers() { readerWriterLock.AcquireReaderLock(Timeout.Infinite); IList<OnlineUser> lst = new List<OnlineUser>(); foreach (OnlineUser var in _OnlineUserLink) { lst.Add(var); } readerWriterLock.ReleaseReaderLock(); return lst; } /// <summary> /// 获取用户信息 /// </summary> /// <param name="name">id</param> /// <returns></returns> public OnlineUser GetOnlineUser(string id) { OnlineUser value = default(OnlineUser); LinkedListNode<OnlineUser> NodeUser; try { readerWriterLock.AcquireReaderLock(Timeout.Infinite); if (userList.TryGetValue(id, out NodeUser)) { value = NodeUser.Value; } } finally { readerWriterLock.ReleaseReaderLock(); } return value; } /// <summary> /// 根据用户名检测是否在线 /// </summary> /// <param name="id"></param> /// <returns></returns> public bool IsOnlineUser(string id) { bool rBool = false; try { readerWriterLock.AcquireReaderLock(Timeout.Infinite); if (userList.ContainsKey(id)) { rBool = true; } } finally { readerWriterLock.ReleaseReaderLock(); } return rBool; } /// <summary> /// 清除所有在线人数 /// </summary> public void Clear() { readerWriterLock.AcquireWriterLock(Timeout.Infinite); userList.Clear(); allUserList.Clear(); _OnlineUserLink.Clear(); readerWriterLock.ReleaseWriterLock(); } #endregion #region 私有方法 /// <summary> /// 重建用户列表排序 /// </summary> /// <param name="UserNode"></param> private void ReNewUser(LinkedListNode<OnlineUser> UserNode) { if (UserNode.List != null) { UserNode.List.Remove(UserNode); } _OnlineUserLink.AddFirst(UserNode); UserNode.Value.LastTime = DateTime.Now; } /// <summary> /// 重建 /// </summary> /// <param name="UserNode"></param> /// <param name="U_LastUrl"></param> private void ReNewUser(LinkedListNode<OnlineUser> UserNode, string U_LastUrl) { if (UserNode.List != null) { UserNode.List.Remove(UserNode); } _OnlineUserLink.AddFirst(UserNode); UserNode.Value.LastTime = DateTime.Now; UserNode.Value.LastUrl = U_LastUrl; } /// <summary> /// 清除到期在线用户 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void ClearTimeOutUser(object sender, System.Timers.ElapsedEventArgs e) { double NextRunTime = timeOut; DateTime _CheckTime = e.SignalTime.AddMilliseconds(timeOut * -1); _UpdateTimer.Stop(); try { readerWriterLock.AcquireWriterLock(Timeout.Infinite); if (_OnlineUserLink.Count > 0) { LinkedListNode<OnlineUser> UserNode = _OnlineUserLink.Last; TimeSpan ts = UserNode.Value.LastTime - _CheckTime; if (ts.TotalMilliseconds <= 0) { if (UserNode.Previous != null) { ts = UserNode.Previous.Value.LastTime - _CheckTime; if (ts.TotalMilliseconds <= 0) NextRunTime = 1; else NextRunTime = ts.TotalMilliseconds; } Remove(UserNode); } else { NextRunTime = ts.TotalMilliseconds; } } _UpdateTimer.Interval = NextRunTime; } finally { readerWriterLock.ReleaseWriterLock(); } _UpdateTimer.Start(); } #endregion }