局域网聊天系统__6.客户端框架实现
来源:互联网 发布:周杰被黑真相知乎 编辑:程序博客网 时间:2024/05/17 06:49
主要包含类:
CUserInfo 和 CChatPacket 和服务器定义的一致
CChatSocket用于和服务器或其他用户交互数据(类里面内置两个指针,分别指向CClientDlg和CChatDlg 以有效指针来辨别和谁通信)
重写OnReceive和OnClose 均调用对应对话框函数处理
CListenSocket用于监听其他用户的连接请求 在OnAccept和OnClose中调用CClientDlg的函数处理
CLogInDlg用与用户输入登录信息
COffMsgDlg 用于显示离线消息
用户点击回复时 调用CClientDlg::CreateChatDlg 该函数根据用户状态创建不同的聊天对话框
CClientDlg和CChatDlg即为核心实现类
- CClientDlg
在登录成功后
与服务器交互
/** 读取并且处理服务器发来的数据包*/void CClientDlg::ReadAndProcessPacket(){ CChatPacket packet; //临时链表用于保存读取的用户链表信息 CObList obList; packet.m_pUserlist = &obList; packet.Serialize(*m_pArchiveIn); switch(packet.m_type) { //收到服务器信息 显示然后退出 case CChatPacket::SERVERMSG: MessageBox(packet.m_strMsg); EndDialog(IDCANCEL); break; //收到用户链表 更新保存的链表并显示 case CChatPacket::USERLIST: //更新链表 UpdateUserList(obList); //刷新显示 UpdateUserListCtrl(); //将自身状态从登录改为在线 m_userinfo.m_eStatue = CUserInfo::ONLINE; break; //收到转发的离线消息 显示 case CChatPacket::MESSAGE: ShowOfflineMsg(packet); break; default: break; }} 与用户交互 1.用户双击请求聊天: /** 双击用户列表的某一用户时 触发*/void CClientDlg::OnDblclkListUser(NMHDR* pNMHDR, LRESULT* pResult){ // TODO: Add your control notification handler code here NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR; if (pNMListView->iItem != -1) { int nSelected = pNMListView->iItem; CString strPeerName = m_ctlUserList.GetItemText(nSelected, 0); //如果不是和自己聊天 if(strPeerName != m_userinfo.m_strName) CreateChatDlg(strPeerName); } *pResult = 0;}/** 负责根据用户状态的不同建立不同的聊天对话框*/void CClientDlg::CreateChatDlg(const CString &strPeerName){ //从用户链表中找到该用户 POSITION pos = NULL; BOOL bFind = FALSE; CUserInfo peeruserinfo; for (pos=m_userlist.GetHeadPosition(); pos!=NULL;) { //找到该用户 peeruserinfo = *(CUserInfo*)m_userlist.GetNext(pos); if (peeruserinfo.m_strName == strPeerName) { bFind = TRUE; break; } } if (bFind) { CChatDlg chatdlg(this, &m_userinfo, &peeruserinfo); if (peeruserinfo.m_eStatue == CUserInfo::ONLINE) { //用户在线 则连接用户弹出对话框 并保存聊天记录 //设置在线聊天模式 chatdlg.SetChatMode(FALSE); if(chatdlg.ConnectToPeer()) { chatdlg.DoModal(); //保存聊天记录 SaveChatRecord(&chatdlg); } } else if (peeruserinfo.m_eStatue == CUserInfo::OFFLINE) { //如果发送的是离线消息 则由主窗口代为发送到服务器 //避免聊天窗口对服务器的再次连接 //设置离线聊天模式 chatdlg.SetChatMode(TRUE); chatdlg.DoModal(); //打包离线消息 CChatPacket packoffmsg; packoffmsg.m_type = CChatPacket::MESSAGE; packoffmsg.m_strMsg = chatdlg.GetChatRecord(); packoffmsg.m_userinfo = m_userinfo; packoffmsg.m_peerUserinfo = peeruserinfo; packoffmsg.m_sendtime = CTime::GetCurrentTime(); //发送数据包 SendPacket(packoffmsg); //保存聊天记录 SaveChatRecord(&chatdlg); } }}
2.用户被动聊天,即响应CListenSocket::OnAccept()
/** 当其他用户请求聊天时 调用此函数接受请求并创建聊天对话框*/BOOL CClientDlg::ProcessPendingAccept(){ //得到与一个聊天对话框相关联的一个CChatSocket CChatDlg chatdlg(this); chatdlg.InitChatSocket(); CChatSocket* pNewSocket = chatdlg.GetChatSocket(); //用该CChatSocket接收连接 SOCKADDR_IN addrPeer; int len = sizeof(SOCKADDR_IN); int ret = m_pListenSocket->Accept(*pNewSocket, (SOCKADDR*)&addrPeer, &len); //找到请求连接的用户的信息 POSITION pos = NULL; CUserInfo* pUserInfo = NULL; BOOL bFind = FALSE; for (pos = m_userlist.GetHeadPosition(); pos!=NULL;) { pUserInfo = (CUserInfo*)m_userlist.GetNext(pos); if (pUserInfo->m_dwIP == addrPeer.sin_addr.S_un.S_addr && pUserInfo->m_eStatue == CUserInfo::ONLINE) { bFind = TRUE; break; } } //找到了则设置对话框对应的数据 显示聊天对话框 if (bFind) { chatdlg.SetUserInfo(&m_userinfo); chatdlg.SetAimUserInfo(pUserInfo); chatdlg.InitArchive(); chatdlg.SetChatMode(FALSE); chatdlg.DoModal(); SaveChatRecord(&chatdlg); } return TRUE;}
//其他主要函数 void ProcessServerClose(); //处理服务器退出或断开连接 BOOL ProcessPendingAccept(); //处理新的用户聊天请求 void SaveChatRecord(CChatDlg* pChatDlg); //保存聊天记录 void CreateChatDlg(const CString& strPeerName); //根据用户状态创建聊天对话框 void ShowOfflineMsg(const CChatPacket& packet); //显示离线消息 void UpdateUserListCtrl(); //更新用户列表显示 void UpdateUserList(CObList& oblist); //收到服务器的用户列表时 更新 void ReadAndProcessPacket(); //读取并处理服务器发来的数据包 void ProcessPendingRead(); //调用ReadAndProcessPacket处理数据 BOOL BeginListen(); //创建并开启监听套接字 void SendPacket(CChatPacket& packet); //向服务器发送数据包 BOOL ConnectToServer(); //连接到服务器 void InitListCtrlSetting(); //初始化用户列表控件设置 BOOL Init(); //客户端初始化//主要数据成员 CObList m_userlist; //用户列表 SOCKADDR_IN m_addrHost; //主机地址(端口为监听套接字端口) CArchive* m_pArchiveOut; //用于向服务器发送数据的文档对象 CUserInfo m_userinfo; //本用户的信息 CArchive* m_pArchiveIn; //用于接收服务器发送的数据的文档对象 CSocketFile* m_pSocketFile; //与服务器通信用的CSocketFile CChatSocket* m_pChatSocket; //与服务器聊天的CChatSocket CImageList* m_pImageList; //用户头像 CListenSocket* m_pListenSocket; //监听套接字
- CChatDlg:
CChatDlg有两种初始化方式,默认构造和直接构造CChatDlg(CWnd* pParent, CUserInfo* puser, CUserInfo* paimuser)
前者用于被动聊天 因为需要先构造CChatDlg用其成员变量m_pChatSocket来作为参数接收连接请求 之后才能得到对方用户信息,可通过SetPeerUserInfo来设置
后者用于主动聊天,此时对方用户信息可以在CClientDlg中得到,因此直接构造。
当聊天为在线聊天时,还需要调用InitArchive获得CSocket序列化支持
CChatDlg主要函数和数据:
// CChatDlg主要函数: public: void ProcessPeerClose(); //当对方关闭聊天对话框时调用 CChatSocket* GetChatSocket(); //得到聊天套接字 void InitChatSocket(); //创建聊天套接字 void SetAimUserInfo(const CUserInfo* puserinfo);//保存对方信息 void SetUserInfo(const CUserInfo* puserinfo); //保存本用户信息 void InitArchive(); //初始化必需的CSocketFile和CArchive对象 void SendPacket(CChatPacket* pPacket); //向对方发送数据包 void DisplaySentMsg(CString strInput); //在聊天记录框中显示自己发送的信息 void DisplayRecvMsg(const CChatPacket& recvpacket);//在聊天记录框中显示接收的信息 ~CChatDlg(); void ProcessPendingRead(); //当聊天套接字可读时,通过该函数处理 CString GetChatRecord(); //得到聊天记录 void SetChatMode(BOOL bOfflineChat); //设置聊天模式(True:离线留言 False 在线聊天) bool ConnectToPeer(); //连接到对方 CChatDlg(CWnd* pParent, CUserInfo* puser, CUserInfo* paimuser);//主动聊天的构造函数 // 主要数据成员 CString m_strChatRecord; //聊天记录 CArchive* m_pArchiveOut; //发送数据的文档对象 CArchive* m_pArchiveIn; //接收数据的文档对象 CSocketFile* m_pSocketFile; //聊天套接字关联的CSocketFIle文件 CChatSocket* m_pChatSocket; //聊天套接字 CUserInfo m_aimuserinfo; //聊天对方的信息 CUserInfo m_userinfo; //本用户的信息 BOOL m_bOfflineChat; //标识聊天类型
主要函数实现
//发送数据: /** 用户点击发送按钮 发送信息 并且更新聊天对话框显示*/void CChatDlg::OnBtnSend(){ // TODO: Add your control notification handler code here //得到输入内容 CString strUserInput; m_ctrlInput.GetWindowText(strUserInput); //为空则不发送 if (strUserInput == "") return; if(m_bOfflineChat) //离线留言 只需要负责界面显示 由主对话框负责发送给服务器 { //清空输入框 m_ctrlInput.SetWindowText(""); //更新聊天框显示 DisplaySentMsg(strUserInput); } else //在线聊天 { //打包数据 CChatPacket msgpacket; msgpacket.m_type = CChatPacket::MESSAGE; msgpacket.m_userinfo = m_userinfo; msgpacket.m_peerUserinfo = m_aimuserinfo; msgpacket.m_strMsg = strUserInput; msgpacket.m_sendtime = CTime::GetCurrentTime(); //发送数据 SendPacket(&msgpacket); //清空输入框 m_ctrlInput.SetWindowText(""); //更新聊天框显示 DisplaySentMsg(strUserInput); }}//接收数据 由CChatSocket::OnReceive调用void CChatDlg::ProcessPendingRead(){ do { CChatPacket packet; packet.Serialize(*m_pArchiveIn); if (packet.m_type == CChatPacket::MESSAGE) { DisplayRecvMsg(packet); } }while(!m_pArchiveIn->IsBufferEmpty());}
完整源代码下载地址点击这里:http://download.csdn.net/detail/wudaijun/4911762
- 局域网聊天系统__6.客户端框架实现
- 局域网聊天系统__3.服务器框架实现
- 局域网聊天系统__5.客户端业务逻辑与框架
- 局域网聊天系统__7.客户端调试与总结
- Java局域网聊天系统(服务器客户端一对一)
- JAVA实现局域网聊天
- [原创]java局域网聊天系统
- 局域网聊天系统详细设计
- 基于局域网的聊天系统
- 局域网LanQQ聊天项目(二)服务器和客户端整体框架的搭建
- 【项目源码】- 【局域网聊天】android实现局域网聊天 - UDP实现
- Delphi实现局域网聊天01
- QT之局域网聊天实现
- Socket实现聊天客户端
- android客户端 j2ee服务器端架构的聊天系统实现思路
- 局域网聊天|权限管理系统设计思路
- 基于C++的局域网聊天系统客户
- 局域网聊天系统__4.服务器调试篇
- 这几天感悟的几句话
- How to do take snapshot image as binary data?
- iOS 17个常用代码整理
- [Erlang 0095] 善用 Erlang module_info
- Storm-Like Projects
- 局域网聊天系统__6.客户端框架实现
- 键盘的相关设置
- How to use VideoIO文章连载
- [Erlang 0096] RabbitMQ Boot Step
- linux tar 文件解压
- Java反编译利器-Jad, Jode, Java Decompiler等及其IDE插件
- 字母和数字的转换——Excel列名
- tcp
- Ruby中new和initialize的区别