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

 

posted on 2010-07-28 11:50  raychn  阅读(1616)  评论(0编辑  收藏  举报