首页 新闻 论坛 群组 Blog 文档 下载 读书 Tag 网摘 搜索 开源 FAQ 第二书店 博文视点 程序员
频道: 研发 数据库 中间件 信息化 视频 .NET Java 游戏 移动 服务: 人才 外包 培训
    图书品种:235680
       
热门搜索: ASP.NET Ajax Spring Hibernate Java

18.3  服务器端底层代码

本章的Web QQ是一个比较复杂的项目,下面将首先从它的底层代码开始讲起。这里的底层代码主要包括两类:一类是指独立性很强的通用代码,这些代码稍加修改就可应用于其他项目中;另一类是指这个项目的一些基础类库,如对实体类、工具类的封装等,它们是这个项目的核心代码。本章将分别从服务器端和客户端两个方面详细讲述这些代码的实现。

本节讲述服务器端底层代码的实现。

服务器端的底层代码包括在MyChat类库工程中,主要有两个文件:sql.cs和implement.cs。其中sql.cs只包括一个类的定义Sql,用来操作数据库。Implement.cs包括的类大体包括:消息类、消息基础类BaseMsg、两人消息类Msg、两人消息表类MsgTable、群内单个用户访问时间类RT、群内所有用户访问时间类RTT、群消息表类GroupMsgTable及其扩展类——群类MyGroup;聊天用户类ChatUser;工具类Tools。下面分别作详细介绍。

18.3.1  数据库操作类Sql

数据库操作类的封装是任何工程都必不可少地,本例当然也不例外。Sql类主要包括两类方法:一类用来直接执行SQL语句,另一类用来执行存储过程。其所包括的各种方法的结构如图18.4所示。

图18.4  Sql类的各种方法

其中的数据库连接字符串的数据库路径采用了绝对路径,读者调试程序时应当做相应的更改。Sql类的具体代码如下:

using System;

using System.Collections.Generic;

using System.Text;

using System.Data.SqlClient;

using System.Data;

namespace MyChat

{

    //数据库操作类

    public class Sql

    {

          private string str = null;                   //数据库连接字符串

          public SqlConnection Con;                    //sql数据连接组件实例化

          public SqlCommand command = new SqlCommand();    //初始化一个SQL命令对象

          public Sql()                                 //类初始化,初始化数据连接

          {

                string path = @"C:\Documents and Settings\Administrator\桌面\tools\

                mychat1.0\Chat";

                //数据库连接字符串

                str="Data Source=.\\SQLEXPRESS;AttachDbFilename=\"" + path +

                "\\app_data\\chat.mdf\";Integrated Security=True;User Instance=True";

                Con = new SqlConnection(str);

          }

          #region SQL语句操作

          // 执行只读数据信息的提取,返回一个datareader

          public SqlDataReader GetReader(string search)

          {

               SqlDataReader Reader;

               if(Con.State != ConnectionState.Open)

                    Con.Open();                           //打开数据库连接

               SqlCommand Com = new SqlCommand(search, Con);

               Reader = Com.ExecuteReader();        //执行SQL语句

               return Reader;                           //返回一个reader

          }

          // 输入查询字符串,返回dataset

          public DataSet getMyDataSet(string sql)

          {

                command.Connection = Con;            //配置command对象

                command.CommandText = sql;           //赋予要执行的语句

                DataSet dt = new DataSet();          //初始化一个数据返回集合

                SqlDataAdapter da = new SqlDataAdapter(command);

                Con.Open();                          //打开连接

                da.Fill(dt);                     //执行语句

                command.Connection.Close();          //关闭连接

                return dt;

          }

          // 执行非查询SQL语句

          public void ExecuteSql(string sql)

          {

                if(Con.State != ConnectionState.Open)

                     Con.Open();                      //如果数据连接关闭,则打开

                SqlCommand Com = new SqlCommand(sql, Con);

                Com.ExecuteNonQuery();               //执行非查询SQL语句

                Con.Close();

          }

          // 执行非查询数据库操作,是否关闭数据库连接  可以选择

          public void ExecuteSql(string sql, bool closeConnection)

          {

                if(Con.State != ConnectionState.Open)

                     Con.Open();                      //如果未打开连接,则打开

                SqlCommand Com = new SqlCommand(sql, Con);

                Com.ExecuteNonQuery();

                if (closeConnection) Con.Close();    //如果需要关闭,则关闭连接

          }

          #endregion

          #region 执行存储过程的代码

          //输入存储过程名称,执行查询存储过程

          public DataSet getDataSet(string produreName)

          {

                command.Connection = Con;            //赋予连接对象

               //执行的类型为存储过程

                command.CommandType = CommandType.StoredProcedure  ;

                command.CommandText = produreName;   //赋予执行的存储过程名字

                DataSet dt = new DataSet();

                SqlDataAdapter da = new SqlDataAdapter(command);

                Con.Open();                          //打开连接

                da.Fill(dt);                     //填充数据

                command.Connection.Close();

                return dt;                           //返回数据集

          }

          //输入存储过程名,执行非查询存储过程

          public bool exec(string produreName)

          {

                bool flag = false;                   //任务是否正确执行,初始化为false

                command.Connection = Con;            //赋予command对象以数据连接

                command.CommandType = CommandType.StoredProcedure;

                command.CommandText = produreName;   //存储过程名称

                try

                {

                    command.ExecuteNonQuery();        //执行存储过程

                    flag = true;                      //正确完成任务

                }

                finally

                {

                    command.Connection.Close();           //关闭连接

                }

                return flag;                         //返回成功与否的标志

          }

          #endregion

      }

}

18.3.2  消息基础类BaseMsg

文本框:  
图18.5  与消息相关的各类

消息是Web QQ的核心任务之一,几乎所有的操作都是围绕消息展开的,所以这里对消息处理进行了实体类封装。消息分两种:两人聊天的消息类和群聊的消息类。它们之间有很多区别,但也有很多相似之处,所以本章定义了一个消息基础类,两人聊天的消息类和群聊的消息类都从基础类继承。与消息直接相关的各类之间的关系如图18.5所示。

消息基础类BaseMsg的代码比较简单,只是封装了几个常用的属性。具体代码如下:

/// <summary>

      /// 消息基础类

      /// </summary>

      public class BaseMsg

      {

           public BaseMsg(string senderName, string message)

           {

                msg = message;                   //消息内容

                sendername = senderName;     //消息发送者

           }

           public BaseMsg(string senderName, string message, DateTime sendtime1)

           {

                msg = message;                   //消息内容

                sendername = senderName;     //消息发送者

                sendtime = sendtime1;            //发送时间

           }

           public BaseMsg(int id1, string senderName, string message, DateTime

           sendtime1)

           {

                msg = message;                   //消息内容

                sendername = senderName;     //消息发送者

                id = id1;                        //消息id

                sendtime = sendtime1;            //发送时间

           }

           private int id = 0;                 //消息的id

           public int ID

           {

                get { return id; }

                set { id = value; }

           }

           private string sendername;              //消息的发送者

           public string SenderName

           {

                get

                {

                    return sendername;

                }

                set

                {

                    sendername = value;

                }

           }

           private string msg;                     //消息内容

           public string Message

           {

                get

                {

                    return msg;

                }

                set

                {

                    if(value.Length > 150)            //消息不能超过150个字符,否则截断

                        value = value.Substring(0, 150);

                    msg = value;

                }

           }

           private DateTime sendtime = DateTime.Now; //发送时间

           public DateTime SendTime

           {

                get

                {

                    return sendtime;

                }

                set

                {

                    sendtime = value;

                }

           }

      }

18.3.3  两人聊天消息类Msg

两人聊天的消息类Msg直接从BaseMsg继承,在BaseMsg基类上另外添加了两个属性:IfRead和IfInDb。IfRead用来标记这条消息是否已经被接收者阅读过;IfInDb用来标记缓存中的此条消息是否已经在数据库中保存,如果保存了,则要考虑数据的同步问题。Msg的具体代码如下:

/// <summary>

     /// 两人聊天时的消息类

     /// </summary>

     public class Msg : BaseMsg

     {

          public Msg(string senderName, string message)

               : base(senderName, message)

          {

          }

          public Msg(int id1, string senderName, string message, DateTime sendtime1, bool ifread1)

               : base(id1, senderName, message, sendtime1)

          {

               ifread = ifread1;            //此条消息是否已经读过

          }

          private bool ifread = false;         //消息初始化未读

          public bool IfRead                     // 是否已经读过

          {

               get

               {

                   return ifread;

               }

               set

               {

                   ifread = value;

               }

          }

          private bool ifInDB = false;         // 是否在数据库中保存有此条记录

          public bool IfInDB

          {

               get

               {

                   return ifInDB;

               }

               set

               {

                   ifInDB = value;

               }

          }

    }

18.3.4  两人聊天消息表类MsgTable

消息都要以集合的形式保存,两人聊天的消息表类是MsgTable。每个聊天用户都有一个单独的MsgTable,这个MsgTable记录着发给此用户的所有消息(包括系统消息)。由于内存毕竟是有限的,所以对每个用户的消息数量进行了一定的限制,超过这个数量后,消息将被存储入数据库,并清空该用户的消息表。属性MaxRecord就是实现这个功能的。属性HaveOtherMsg标记的是此用户的未读消息是否已经全部载入了内存。MsgTable定义了两个Add方法,分别用于处理聊天用户类初始化和用户发言操作。具体代码如下:

// 两人聊天的消息表

public class MsgTable

{

     private int maxrecord = 30;         //消息表中最多存放的记录数目

     public int MaxRecord

     {

          get { return maxrecord; }

          set { maxrecord = value; }

     }

     private ArrayList list;             //存放消息的arraylist

     private bool haveothermsg = false;  //数据库中是否还有未读消息

     public bool HaveOtherMsg

     {

          set { haveothermsg = value; }

          get { return haveothermsg; }

     }

     public ArrayList List               //存放消息用

     {

          get

          {

              return list;

          }

     }

     public MsgTable()

     {

          list = new ArrayList();          //类初始化时,初始化一个消息列表存放地

     }

     public MsgTable(Msg msg1)

     {

          list = new ArrayList();

          this.Add(msg1);                  //类初始化时,类中便有一条消息

     }

     //初始化用户类时专用

     public void Add(Msg msg1)

     {

          //内存块已满,首先把已读数据存入数据库,释放部分内存,

          //如果内存中的数据都是未读,把所有数据都存入数据库,释放全部内存。

          if(list.Count >= MaxRecord)

          {

                Sql s = new Sql();           //初始化数据库操作类

                string insertstr = "";       //插入字符串

                string updatestr = "";       //更新字符串

                //用户初始化时 只取未读数据,所以内存中的所有已读数据都需要更新为ifread=0,

                //或插入数据库。清除内存中已读数据

                for(int i = 0; i < MaxRecord; i++)

                {

                    if(((Msg)(list[i])).IfRead)   //已读

                    {

                         //此条聊天记录存在于数据库中,则更新其为已读状态

                         if((((Msg)(list[i])).IfInDB))

                               updatestr += " or id = " + (((Msg)(list[i])).ID.ToString());

                         else              //位在数据库中,则插入数据库

                         {

                               insertstr = "insert msg(sendername,receivername,msg, endtime,fread) values('";

                               insertstr += ((Msg)list[i]).SenderName + "','" + System. Web.HttpContext.Current.User.Identity.Name + "','" + ((Msg)list[i]).Message + "','";

                               insertstr += ((Msg)list[i]).SendTime + "','" + "0" + "')";

                                             //执行插入操作

                              s.ExecuteSql(insertstr, false);

                         }

                         list.RemoveAt(i); //释放内存

                     }

                }

                if(updatestr != "")          //如果有需要更改为已读状态的则统一执行更改操作

                     s.ExecuteSql("update msg set  ifread = 0 where 1=2 " + updatestr, false);

                //从内存中清除已读消息后,如果内存块仍然满,则把所有消息都存入数据库,清空内存
                //块,以待现在聊天用

                if(list.Count >= MaxRecord)

                {

                    for(int i = 0; i < MaxRecord; i++)

                    {

                         //消息没有在数据库中,则插入数据库

                         if (!(((Msg)list[i]).IfInDB))

                         {

                               insertstr = "insert msg(sendername,receivername,msg, sendtime,ifread) values('";

                               insertstr += ((Msg)list[i]).SenderName + "','" + System.Web.HttpContext.Current.User.Identity.Name + "','" + ((Msg)list[i]).Message + "','";

                               insertstr += ((Msg)list[i]).SendTime + "','" + "1" + "')";

                               s.ExecuteSql(insertstr, false);

                         }

                    }

                    list.Clear();         //清空存放消息的数组

              }

              s.Con.Close();                //关闭数据库连接

          }

          list.Add(msg1);                  //增加一条聊天记录

     }

     //用户发言时专用

     public void Add(string sendername, string message)

     {

          Add(new Msg(sendername, message));

     }

}

18.3.5  群消息表类GroupMsgTable

群消息与两人聊天的消息有所不同。群消息的处理机制是:每个群都包括一个群消息表GroupMsgTable用来记录群内的所有消息,而这个群消息表又包括一个记录群内用户访问时间的属性ReceiveTime。ReceiveTime是用户访问时间表类RTT的一个实例,RTT又是RT的集合。RT、RTT和GroupMsgTable类的实现代码如下:

// 记录群消息中单个用户的访问时间

public class RT

{

     private string username;           //用户账号

     public string UserName

     {

          set { username = value; }

          get { return username; }

     }

     private DateTime time = DateTime.Now;   //用户访问时间

     public DateTime Time

     {

          get { return time; }

          set { time = value; }

     }

     public RT(string un)                //初始化时指定账号名

     {

          username = un;

     }

}

/// <summary>

/// 记录一个群中所有用户的访问时间。

/// </summary>

public class RTT : ArrayList

{

     public override int Add(object value)

     {

           return base.Add(value);

     }

}

// 单个群的消息表类

public class GroupMsgTable

{

     private int maxrecord = 100;        //存放群消息的内存块最多存放的消息数目

     public int MaxRecord

     {

          get { return maxrecord; }

          set { maxrecord = value; }

     }

     private int id = 0;                 //初始化群id

     public int ID

     {

          get { return id; }

          set { id = value; }

     }

     protected ArrayList list;           //群消息的arraylist

     public ArrayList List

     {

          get

          {

              return list;

          }

     }

     private bool haveothermsg = false;  //除内存的消息外,是否数据库中还有群消息

     public bool HaveOtherMsg

     {

          set { haveothermsg = value; }

          get { return haveothermsg; }

     }

     public GroupMsgTable()              //初始化一个空群消息类

     {

          list = new ArrayList();

     }

     public GroupMsgTable(string groupid) //初始化的类指定了群id,主要用于从数据库中取

     //出的群消息

     {

          id = int.Parse(groupid);

          list = new ArrayList();

     }

     //指定群id,并且默认添加一条群消息

     public GroupMsgTable(BaseMsg msg1, string groupid)

     {

          id = int.Parse(groupid);

          list = new ArrayList();

          this.Add(msg1);

     }

     private RTT receivetime = new RTT(); //此群中所有用户的访问时间

     public RTT ReceiveTime                  // 群所有用户最近一次接受群消息的时间

     {

          get

          {

              return receivetime;

          }

          set { receivetime = value; }

     }

     //群消息过期时间

     private TimeSpan ts = new TimeSpan(500);

     private int askdbnum = 0;               //访问数据库的次数

     public int AskDbNum

     {

          get { return askdbnum; }

          set { askdbnum = value; }

     }

     //发布一条群消息

     public void Add(BaseMsg msg1)

     {

          //内存块已满,首先把过期时刻之前的数据存入数据库,释放部分内存,

          //如果内存仍满,把所有数据都存入数据库,释放全部内存,IfInDb=true 。

          if(list.Count >= MaxRecord)          //内存块已经满

          {

                Sql s = new Sql();              //数据库操作类

                string insertstr = "";          //插入字符串

                //清除内存中过期数据

                for(int i = 0; i < MaxRecord; i++)

                {

                     insertstr = "insert groupmsg(groupid,sendername,sendtime,msg) values(" + id.ToString() + ",'";                   //插入字符串

                     //过期

                     if(((BaseMsg)(list[i])).SendTime < DateTime.Now - ts)

                     {

                           insertstr += ((BaseMsg)list[i]).SenderName + "','" + ((BaseMsg)list[i]).SendTime + "','" + ((BaseMsg)list[i]).Message + "')";

                           s.ExecuteSql(insertstr, false);

                           list.RemoveAt(i);        //释放内存

                     }

                }

                if(list.Count >= MaxRecord) //内存块仍满,所有数据都存入数据库,释放全部

                                          内存,

                {

                     //所有数据存入数据库

                     for(int i = 0; i < MaxRecord; i++)

                     {

                        insertstr = "insert groupmsg(groupid,sendername,sendtime,msg) values(" + id.ToString() + ",'";

                        insertstr += ((BaseMsg)list[i]).SenderName + "','" + ((BaseMsg)list[i]).SendTime + "','" + ((BaseMsg)list[i]).Message + "')";

                        s.ExecuteSql(insertstr, false);

                     }

                     list.Clear();                //清空内存块

                     haveothermsg = true;     //表明数据库中存有数据

                }

                s.Con.Close();                  //关闭数据库连接

          }

          list.Add(msg1);                       //增加消息记录

     }

}

18.3.6  群类MyGroup

群类MyGroup继承自GroupMsgTable类,只是类GroupMsgTable基础上添加了一个方法ReceiveMsg,用来接收群消息。接收一条群消息的处理逻辑如图18.6所示。

图18.6  接收群消息的流程图

MyGroup的实现代码如下:

//群的类

    public class MyGroup : GroupMsgTable

    {

         public MyGroup(string groupid)

              : base(groupid)                           //类初始化

         { }

         //接收群消息

         public GroupMsgTable ReceiveMsg()

         {

              GroupMsgTable mymsg = new GroupMsgTable();//用于存放接收到的消息

              DateTime lt = DateTime.Now.AddMinutes(-3);    //上次接收消息的时间

              int tempid = -1;                  //此用户在本群的receivetime中的索引。

              //下面得到该用户最近一次访问该群的时间

              string usern = System.Web.HttpContext.Current.User.Identity.Name;

//当前用户名

              //遍历群中用户访问时间数组,找到自己访问的时间和在数组中的索引

              for(int i = 0; i < this.ReceiveTime.Count; i++)

              {

                   if(((RT)ReceiveTime[i]).UserName == usern)//找到本用户

                   {

                        lt = ((RT)ReceiveTime[i]).Time;

                        tempid = i;

                        break;

                   }

              }

              //需要从数据库中取数据

              if(this.HaveOtherMsg == true)

              {

                   string str = "select groupid,sendername,sendtime,msg from groupmsg where groupid ="

                   +this.ID.ToString() + " and sendtime>'" + lt + "'";  //构造字符串

                   Sql s = new Sql();

                   SqlDataReader reader = s.GetReader(str);  //得到数据

                   while (reader.Read())         //把数据库中的群消息全部返回给接收者

                   {

                        mymsg.Add(new BaseMsg(reader["sendername"].ToString(), reader["msg"].ToString(),

                        DateTime.Parse(reader["sendtime"].ToString())));

                   }

                   reader.Close();                       //关闭连接

                   this.AskDbNum++;                      //访问数据库的次数增一

                   //如果超过50次,即认为群中所有人都从数据库中取了一次数据,没有需要从数据库

                   //中取数据了。

                   if(this.AskDbNum > 50)

                   {

                         this.AskDbNum = 0;                //重新计算访问数据库的次数

                         this.HaveOtherMsg = false;

                   }

              }

              //遍历内存块中的数据

              for(int i = 0; i < this.list.Count; i++)

              {

                   //如果内存中的群消息的发送时间在自己上次访问之后,并且这条消息不是自己发送的

                   if(((BaseMsg)list[i]).SendTime >= lt && ((BaseMsg)list[i]).Sender

                   Name != usern)

                   {

                        mymsg.Add((BaseMsg)list[i]);       //添加到数组,返回给接收者

                   }

              }

              //如果找到了用户在接收消息列表中的索引,则更新接收时间

              if(tempid != -1)

                   ((RT)ReceiveTime[tempid]).Time = DateTime.Now;

              Else                                      //否则新建接收时间

              {

                   ReceiveTime.Add(new RT(usern));

              }

              return mymsg;                             //返回群消息

      }

}

18.3.7  聊天用户类ChatUser

每个聊天用户对应一个ChatUser类,当此类初始化时只是取得用户账号和ID,不加载任何相关信息。当类消失时,做一些清理工作,把缓存中的数据存入数据库。清理工作的大致流程是:遍历自己的消息集,如果这条消息在数据库中不存在,则插入数据库;如果在数据库中存在,并且已读状态发生了改变,则更新数据库中的记录。聊天用户类ChatUser的代码如下:

// 聊天程序用户类

public class ChatUser

{

     private HttpContext context = HttpContext.Current;  //当前的运行上下文

     private int userid;                                 //用户id

     private string username;                            //账号名

     public int Userid                                     // 用户ID

     {

          get

          {

               return userid;

          }

     }

     public string UserName                            // 账号名

     {

          get

          {

              return username;

          }

     }

     //上线与否的过期时间,超过这个时间即认为用户已经离线

     private DateTime willtime = DateTime.Now.AddMinutes(1);

     public DateTime WillTime

     {

          get

          {

              return willtime;

          }

          set

          {

              willtime = value;

          }

     }

     //用户消息组,所有发给自己的消息都存储在这里

     private MsgTable message = new MsgTable();

     public MsgTable Message                            // 存储别人发给自己的消息

     {

          get

          {

              return message;

          }

          set

          { message = value; }

     }

     public ChatUser()                              //初始化时,取得id和name

     {

          username = System.Web.HttpContext.Current.User.Identity.Name ; 

          userid = int.Parse(tools.GetUserId(username));

     }

     //析构函数,本实例消失时把内存中的数据存入数据库

     ~ChatUser()

     {

          Sql s = new Sql();                           //数据库操作类

          for(int i = 0; i < Message.List.Count; i++)

          {

               string str = "";

               //判断此条聊天记录在数据库中是否存在,数据库中没有,则插入数据库

               if(((Msg)Message.List[i]).IfInDB == false)

               {

                     str = "insert msg(sendername,receivername,msg,sendtime,ifread)

                     values('";

                     string ifread = "1";             //此条记录是否已读,1为未读

                     //已读

                     if (((Msg)Message.List[i]).IfRead == true) ifread = "0";

                     str+=((Msg)Message.List[i]).SenderName + "','" + UserName + "','" +
                          ((Msg)Message.List[i]).Message + "','";

                     str += ((Msg)Message.List[i]).SendTime + "','" + ifread + "')";

                     s.ExecuteSql(str);                   //执行插入操作

               }

               //数据库中存在这条记录,且内存中的记录由未读变为了已读,则更改数据库中的状态

               else if (((Msg)Message.List[i]).IfRead == true)

               {

                     string updatestr = "update msg set ifread=0 where id =" + ((Msg)

                     Message.List[i]).ID.ToString();

                     s.ExecuteSql(updatestr);

               }

          }

      }

}

18.3.8  工具类Tools

为了应用程序方便,此处把本项目中常用到的功能封装在了tools类中。本类中的各个方法之间基本上没什么直接联系,可以单独使用,并且绝大部分是静态方法。各个方法的简要说明见表18-8所示。

表18-8                                                      tools类各方法说明

方  法  名

功    能

参 数 说 明

返  回  值

UpdateSelfTime

更新自己的最终离线时间

GetUserId

根据账号得到id

Username用户账号

相应的id

GetMyUserName

根据id得到账号

Userid用户ip

相应的账号

SetOnlinStatus

设置自己在线和隐身的状态

Status要设置成的状态

CheckMessage

检测某人是否给自己发送了最新消息

Sn要检测者的账号

真假值

GetSysMsgNum

得到自己的系统消息数量

消息数目

续表

方  法  名

功    能

参 数 说 明

返  回  值

LoadStr

加载某类联系人显示的字符串

Type联系人类别;ifhavemsg本类联系人中是否有新消息

用于客户端显示的字符串

LoadGroupStr

加载自己群显示的字符串

用于客户端显示的字符串

AddNewUser

加载一个新的聊天用户类

Context当前运行上下文

操作是否成功

Encrypt

加密

strText待加密的字符串;strEncrKey密钥

加密后的字符串

这里介绍一下LoadStr方法的处理流程。LoadStr用于取得自己某类联系人显示的字符串。它有一个输出参数ifhavemsg,表示此类中是否有新消息。整个方法的处理流程如图18.7所示。

图18.7  LoadStr()方法的流程图

AddNewUser方法是当用户登录时,或者用户在线但用户类的缓存被回收的情况下调用。其处理逻辑大致分为3个步骤,如图18.8所示。

图18.8  AddNewUser方法的流程图

Tools类的实现代码如下:

//工具类,封装一些常用的函数

    public class tools

    {

          Sql s;                       //数据库操作类

          int selfid;                  //用户id

          string selfname;             //用户名

          public tools()               //类实例化时,给变量赋值

          {

               s = new Sql();

               if(System.Web.HttpContext.Current.User.Identity.IsAuthenticated)

               {

                    selfname = System.Web.HttpContext.Current.User.Identity.Name; 

                    selfid = int.Parse(tools.GetUserId(selfname ));

               }

          }

          //更新自己的离线时间, 保持自己的上线状态

          public static void UpdateSelfTime()

          {

               //如果未登录,则返回

               if (!System.Web.HttpContext.Current.User.Identity.IsAuthenticated)

               return;

               HttpContext co = System.Web.HttpContext.Current;

               //本用户信息为空

               if(co.Cache[System.Web.HttpContext.Current.User.Identity.Name] == null)

               {

                     ChatUser user = new ChatUser();

                     //增加一个用户聊天类实例

                     co.Cache.Insert(user.UserName, user);

               }

               //更新自己的离线时间

               ((ChatUser)(co.Cache[System.Web.HttpContext.Current.User.Identity.

               Name])). WillTime = DateTime.Now.AddSeconds(30);

          }

          //根据id获得name

          public static string GetUserId(string username)

          {

               string result="";

               Sql ms = new Sql();

              DataTable dt = ms.getMyDataSet("select userid from userinfo where

              username='"+username +"'").Tables[0];

              if(dt.Rows.Count > 0)

                   result = dt.Rows[0][0].ToString();

              return result;

          }

          //根据name获得id

          public static string GetMyUserName(string userid)

          {

               string result = "";

               Sql ms = new Sql();

               DataTable dt = ms.getDataSet("select username from userinfo where

               userid='" + userid + "'").Tables[0];

               if(dt.Rows.Count > 0)

                    result = dt.Rows[0][0].ToString();

               return result;

          }

          // 用户设置自己的上线状态,隐身还是上线

          // 上线状态设置 1上线,0隐身

          public static void SetOnlineStatus(string status)

          {

               string user = System.Web.HttpContext.Current.User.Identity.Name;

                                                        //用户id

               Sql ms = new Sql();

               //更新自己的上线状态

               ms.ExecuteSql("update userinfo set ifshowonline=" + status + " where

               username='" + user+"'");

          }

          // 判断某用户是否给自己发送了新消息

          //sn  发送者姓名

          //返回ture 有新消息;false没有消息

          public bool CheckMessage(string sn)

          {

               bool b = false;                              //默认没有发消息

               //内存中存在的聊天记录id 字符串

               string temp = "0";

               ChatUser my = (ChatUser)(HttpContext.Current.Cache[selfname]);   //获

               //得聊天用户类

               if(my == null)//如果没有了这个用户信息,初始化一个

               {

                    AddNewUser(HttpContext.Current);          //添加一个聊天用户信息类

                    my = (ChatUser)(HttpContext.Current.Cache[selfname]);

               }

               //遍历自己的信息列表

               for(int i = 0; i < my.Message.List.Count; i++)

               {

                    //如果某人给自己发送了消息,并且未读,说明有消息,返回

                    if(((Msg)(my.Message.List[i])).SenderName==sn && ((Msg)(my.Message.

                    List[i])).IfRead == false)

                    {

                        b = true;

                        return b;

                    }

                    temp += ("," + ((Msg)(my.Message.List[i])).ID);   //保存已经检测

                    //过的消息id

               }

               if(my.Message.HaveOtherMsg == true)      //数据库中还有未读消息

               {

                    Sql q = new Sql();                    //构造数据操作类

                    //数据读取类

                    SqlDataReader reader = q.GetReader("Select [id] From  msg  Where

                    [receivername] ='"

                    + selfname + "' and sendername='" + sn + "' and ifread=1 and id

                    not in (" + temp + ") ");

                    //有新消息

                    if(reader.HasRows)

                    {