C#仿QQ聊天程序v1.0(客户端管理类)[易学网]
ChatClientLib类是本程序相当重要的一个类,包括监听消息,用户管理,发送消息及处理未读消息等功能。请结合其它类来认真学习这个程序。
代码
/// <summary>
/// 聊天程序管理类
/// </summary>
public class ChatClientLib
{
private IConnectionList _Connections = null; //联系人列表
private ChatConnection _CurrentConnection = null; //当前联系人对象
private IList _SendMsgProxyList = new ArrayList(); //与用户聊天打开的聊天窗口
private ArrayList _NotifyList = new ArrayList();//收到未查看消息列表
private TcpListener _ServerListener = null; //本地消息监听器
private Thread _ServerListenerThread = null; //监听器使用的线程
private bool _ServerRunning = false;//运行服务器标志
private IPAddress _LocalServerIP; //本地服务器地址
private int _LocalServerPort = 5858;//本地服务器端口
//易学原创作品,如转载请注明出处 by 易学网 www.vjsdn.net
private IMessageContainer _MessageHistory = new NullLog();
public IMessageContainer MessageHistory { get { return _MessageHistory; } set { _MessageHistory = value; } }
//构造器
public ChatClientLib(IConnectionList Connections)
{
_LocalServerIP = Dns.GetHostAddresses(Dns.GetHostName())[0];
_Connections = Connections;
_CurrentConnection = new ChatConnection(Loginer.Current.AccountName, Loginer.Current.Account,
Loginer.Current.FactoryCode, _LocalServerIP.ToString(), _LocalServerPort, ChatState.Online);
}
//未读消息列表
public ArrayList NotifyList { get { return _NotifyList; } }
//在线用户列表
public IConnectionList Connections { get { return _Connections; } set { _Connections = value; } }
//当前用户连接(登录的用户)
public ChatConnection CurrentConnection { get { return _CurrentConnection; } }
private frmShowMessage _ShowMsgForm = new frmShowMessage();
private void ShowMessage(string msg)
{
_ShowMsgForm.ShowMessage(msg);
ChatCommon.ShowWindow(_ShowMsgForm.Handle, 1);
ChatCommon.SetForegroundWindow(_ShowMsgForm.Handle);
}
//启动聊天服务器程序. 参数说明 ip:本地消息服务器IP地址; port:端口
public void StartMessageServer(string localServerIp, int localServerPort)
{
if (_ServerRunning) return;
_LocalServerIP = IPAddress.Parse(localServerIp);
_LocalServerPort = localServerPort;
//构建监听器
_ServerListener = new TcpListener(_LocalServerIP, _LocalServerPort);
_ServerListener.Start(255);
_ServerRunning = true;
//启动线程
_ServerListenerThread = new Thread(new ThreadStart(DoStartServerListener));
_ServerListenerThread.IsBackground = true;
_ServerListenerThread.Start();
this.UpdateOnlineState(1);
}
//关闭聊天服务器程序.
public void StopMessageServer()
{
_ServerRunning = false;
_ServerListener.Stop();
_ServerListenerThread.Abort("101");
_ServerListenerThread = null;
//登出,删除在线记录
this.UpdateOnlineState(0);
}
/// <summary>
///启动聊天服务器程序.
/// </summary>
private void DoStartServerListener()
{
try
{
//监听客户连线请求
while (_ServerRunning)
{
if (_ServerListener == null) return; //防止其它地方关闭监听器
Socket socket = _ServerListener.AcceptSocket(); //有客户请求连接
if (socket == null) continue;
byte[] buffer = new Byte[socket.ReceiveBufferSize];
int i = socket.Receive(buffer); //接收请求数据.
if (i <= 0) continue;
//处理对象流
if (ChatCommon.IsObjectStream(buffer))
{
_MessageHistory.AddMessage("接受到服务器发送的对象数据.");
DoAnalyzeObject(buffer);
socket.Close();
continue;
}
socket.Close();
}
}
catch (Exception ex)
{
if (ex is ThreadAbortException)
{
if ((ex as ThreadAbortException).ExceptionState.ToString() == "101")
_ServerRunning = false;
}
}
}
/// <summary>
/// 获取用户头像
/// </summary>
/// <param name="account"></param>
/// <returns></returns>
private System.Drawing.Image GetUserPhoto(string account)
{
return ChatCommon.GetImage("chat_woman.ico");
}
/// <summary>
/// 发送消息
/// </summary>
public void SendToClient(ChatConnection conn, cmdBase message)
{
TcpClient client = new TcpClient();
ChatCommon.TryConnect(client, conn.IP, conn.Port);
byte[] data = ChatCommon.GetObjectArray(message);
if (client.Connected) client.Client.Send(data);
client.Close();
}
/// <summary>
/// 分析接受到的数据(字节数组)
/// </summary>
/// <param name="buffer"></param>
private void DoAnalyzeObject(byte[] buffer)
{
object o = ChatCommon.GetObject(buffer);
if (o is cmdMessage)//普通消息
{
cmdMessage msg = o as cmdMessage;
_MessageHistory.AddMessage(msg.Sender + "说:" + msg.Content);
//当收到消息,如果有打开与发送者聊天的窗口,则显示消息.否则闪烁图标.
ISendMsgProxy proxy = GetSendMsgProxy(msg.Sender);
if (proxy == null)
{
_Connections.AddReceivedMessage(msg.Sender, msg.Content);
_Connections.FlashConnection(msg.Sender);
_NotifyList.Add(new NotifyItem(NotifyType.Message, msg.Sender));
}
else
{
proxy.ShowMessage(ShowMessageType.ShowTargetMessage, msg.Content);
}
}
else if (o is cmdNotifyOnline) //好友通知上线
{
cmdNotifyOnline msg = o as cmdNotifyOnline;
ChatConnection conn = new ChatConnection(msg.NickName, msg.Sender, msg.FactoryCode, msg.IP,
msg.Port, ChatState.Online);
_Connections.AddConnection(conn);
}
else if (o is cmdExit) //好友通知上线
{
_Connections.RemoveConnection((o as cmdExit).Sender);
}
}
//增加发送消息窗体
public void AddSendMsgProxy(ISendMsgProxy proxy)
{
if (_SendMsgProxyList.IndexOf(proxy) < 0)
_SendMsgProxyList.Add(proxy);
}
//获取发送消息窗体
private ISendMsgProxy GetSendMsgProxy(string account)
{
for (int i = 0; i <= _SendMsgProxyList.Count - 1; i++)
{
ISendMsgProxy proxy = _SendMsgProxyList[i] as ISendMsgProxy;
if (proxy.TargetConnection.Account == account) return proxy;
}
return null;
}
//增加一个用户连接
private void AddClient(ChatConnection client)
{
//有相同的IP存在,不加载
object o = _Connections.GetConnection(client.Account);
if (o == null)
_Connections.AddConnection(client);
}
//登出
public void Logout()
{
IList list = _Connections.GetConnections();
cmdExit msg = new cmdExit(_CurrentConnection.Account);
//通知所有好友
foreach (ChatConnection conn in list)
{
if (conn == _CurrentConnection) continue;
if (conn.ConnectionState == ChatState.Online)
SendToClient(conn, msg);
}
_Connections.CloseAll(false);//关闭所有连接
if (_MessageHistory != null) _MessageHistory.AddMessage("登出成功!");
}
//发送消息给所有用户
public void SendToAllClient(cmdBase message)
{
IList list = _Connections.GetConnections();
foreach (ChatConnection conn in list)
{
if (conn.Account == Loginer.Current.Account) continue;
if (conn.ConnectionState != ChatState.Online) continue;
SendToClient(conn, message);
}
}
//显示发送消息窗体
public void ShowSendMsgForm(ChatConnection conn)
{
ISendMsgProxy proxy = GetSendMsgProxy(conn.Account);
if (proxy == null)
{
proxy = frmSendMessage.Execute(this, this.CurrentConnection, conn);
AddSendMsgProxy(proxy);
}
//有未读消息
if (conn.ReceivedMessage.Count > 0)
{
proxy.ShowMessage(ShowMessageType.ShowTargetMessage, conn.ReceivedMessage);
conn.ReceivedMessage.Clear();
_Connections.StopFlash(conn.Account);
}
proxy.ShowMe();
}
//处理系统通知.优先处理最后一个消息.处理完毕删除通知.
public void ProcessNotify()
{
NotifyItem item = _NotifyList[_NotifyList.Count - 1] as NotifyItem;//先处理最后的消息
if (item.NotifyType == NotifyType.Information)
{
ShowMessage(item.Content.ToString());
}
else if (item.NotifyType == NotifyType.Message)
{
string account = item.Content.ToString();
ChatConnection conn = _Connections.GetConnection(account);
if (conn != null) ShowSendMsgForm(conn);
}
_NotifyList.RemoveAt(_NotifyList.Count - 1); //删除最后一个通知
}
//删除发送消息窗体
public void RemoveSendMsgProxy(ISendMsgProxy frmSendMessage)
{
_SendMsgProxyList.Remove(frmSendMessage);
}
//显示连接消息
public void ShowConnection(ChatConnection conn)
{
frmConnectionInfo.ShowConnection(conn);
}
//加载用户列表
public void LoadUserList(ShowUser type)
{
DataTable dt = ChatDAL.GetOnlineUsers();
IList list = new ArrayList();
_Connections.CloseAll();
_Connections.ShowUserType = type;
foreach (DataRow row in dt.Rows)
{
ChatConnection conn = CreateChatConnection(row);
//当前处理的连接对象是自己,放第一行显示
if (row["Account"].ToString() == Loginer.Current.Account)
_Connections.AddConnection(0, conn);
else
_Connections.AddConnection(conn);
}
}
//DataRow转换为ChatConnection对象
private ChatConnection CreateChatConnection(DataRow row)
{
ChatConnection conn = new ChatConnection();
conn.Account = row["Account"].ToString();
conn.ConnectionState = ChatState.Online;
conn.DisplayName = row["AccountName"].ToString();
conn.IP = row["NativeIP"].ToString();
conn.Port = int.Parse(row["NativePort"].ToString());
conn.FactoryCode = row["FactoryCode"].ToString();
return conn;
}
//更新用户状态.
public void UpdateOnlineState(int state)
{
//保存用户在线记录
ChatDAL.UpdateOnlineState(Loginer.Current.Account, _LocalServerIP.ToString(), _LocalServerPort, state);
}
}
//易学原创作品,如转载请注明出处 by 易学网 www.vjsdn.net