首页 MFC+Winsock类c_s聊天程序开发(略修改).doc

MFC+Winsock类c_s聊天程序开发(略修改).doc

举报
开通vip

MFC+Winsock类c_s聊天程序开发(略修改).docMFC+Winsock类c_s聊天程序开发(略修改).doc 案例开发与分析——聊天程序的开发 一、客户端 任务1:创建客户端框架程序,设计用户界面,并实现与服务器的连接。 1. 创建一个空白工作区,并命名为Chat。 2. 在Chat工作区,用MFC AppWizard创建基于对话框的项目ChatClient,并在Step2中 选中Windows Socket选项。 3. 在对话框中添加控件,如下图所示: 4. 对话框中的控件属性如下表: 表1 控件属性 控件类型 控件ID 其他 Caption...

MFC+Winsock类c_s聊天程序开发(略修改).doc
MFC+Winsock类c_s聊天程序开发(略修改).doc 案例开发与分析——聊天程序的开发 一、客户端 任务1:创建客户端框架程序, 设计 领导形象设计圆作业设计ao工艺污水处理厂设计附属工程施工组织设计清扫机器人结构设计 用户界面,并实现与服务器的连接。 1. 创建一个空白工作区,并命名为Chat。 2. 在Chat工作区,用MFC AppWizard创建基于对话框的项目ChatClient,并在Step2中 选中Windows Socket选项。 3. 在对话框中添加控件,如下图所示: 4. 对话框中的控件属性如下表: 表1 控件属性 控件类型 控件ID 其他 Caption List Box IDC_LIST_MESSAGE 不选Sort List Box IDC_LIST_ONLINE_USERS 不选Sort Edit Box IDC_EDIT_MESSAGE 选中Multiline和VerticalScroll Radio Button IDC_RADIO_GROUP 群聊 Radio Button IDC_RADIO_PRIVATE 私聊 Button IDC_BUTTON_LOGIN 登录 Button IDC_BUTTON_LOGOUT 退出 5. 用ClassWizard为控件对象定义相应的成员变量,如下表所示: 表2 控件对应成员变量 控件ID 控件类型 成员变量名 IDC_EDIT_MESSAGE CString m_strMessage IDC_LIST_MESSAGE CListBox m_listMessage IDC_LIST_ONLINE_USERS CListBox m_listUsers 6. 添加对话框,ID为IDD_DIALOG_LOGIN,Caption为“登录”。 7. 在对话框中添加控件,如下图所示: 8. 对话框中的控件属性如下: 表3 登录对话框控件属性 控件类型 控件ID 其他 Caption Edit Box IDC_EDIT_IP Edit Box IDC_EDIT_PORT Edit Box IDC_EDIT_USERNAME Edit Box IDC_EDIT_PASSWORD 选Styles->Password Button IDOK 连接 选Styles->Default Button Button IDCANCEL 取消 9. 添加一个新类,类名为CLogin,基类为CDialog,Dialog ID为IDD_DIALOG_LOGIN。 10. 用ClassWizard为对话框的控件对象定义成员变量,如下表所示: 表4 登录对话框控件对应成员变量 控件ID 控件类型 成员变量名 IDC_EDIT_IP CString m_strIP IDC_EDIT_PASSWORD CString m_strPassword IDC_EDIT_PORT UINT m_nPort IDC_EDIT_USERNAME CString m_strUserName 11. 为CChatClientDlg类添加“登录”按钮的单击事件消息处理函数OnButtonLogin(), 并添加如下代码:(在client.cpp中添加login.h) CLoginDlg dlg; int nRet = -1; nRet = dlg.DoModal(); 编译项目并运行,单击登录按钮,看看运行情况。 12. 添加一个从CSocket类派生的新类CMySocket,添加类型为CChatClientDlg*的成员变 量m_pDlg,并修改默认构造函数和析构函数如下:(需要添加afxsock.h和 CchatClientDlg.h的包含(后期改为ChatClientDlg类的声明)) CMySocket::CMySocket(CChatClientDlg *pDlg) { m_pDlg = pDlg; } CMySocket::~CMySocket() { m_pDlg = NULL; } 13. 为CChatClientDlg类添加类型为CMySocket*的成员变量m_pMySocket,类型为BOOL 的成员变量m_bGroupChat。(在chatDlg.h中添加class MySocket;一行声明先。) 14. 在CChatClientDlg::OnInitDialog()中添加如下代码: // TODO: Add extra initialization here m_bGroupChat = TRUE; // 默认聊天方式为群聊 ((CButton*)GetDlgItem(IDC_RADIO_GROUP))->SetCheck(TRUE); ((CButton*)GetDlgItem(IDC_BUTTON_LOGOUT))->EnableWindow(FALSE); ((CEdit*)GetDlgItem(IDC_EDIT_MESSAGE))->EnableWindow(FALSE); 15. 在CChatClientDlg类的OnButtonLogin()中添加如下代码:(解决 方案 气瓶 现场处置方案 .pdf气瓶 现场处置方案 .doc见习基地管理方案.doc关于群访事件的化解方案建筑工地扬尘治理专项方案下载 为:在MySocket.h 中,添加类ChatClientDlg类的声明,在ChatClientDlg头文件,添加#include”Mysocket.h” void CChatClientDlg::OnButtonLogin() { // TODO: Add your control notification handler code here CLoginDlg dlg; int nRet = -1; nRet = dlg.DoModal(); // 新增加的代码 switch(nRet) { case IDOK: m_pMySocket = new CMySocket(this);//这行要出问题 if(!m_pMySocket->Create()) { delete m_pMySocket; m_pMySocket = NULL; AfxMessageBox("创建套接字失败~"); return; } if(!m_pMySocket->Connect(dlg.m_strIP, dlg.m_nPort)) { delete m_pMySocket; m_pMySocket = NULL; AfxMessageBox("连接服务器失败~"); return; } ((CButton*)GetDlgItem(IDC_BUTTON_LOGOUT))->EnableWindow(TRUE); ((CButton*)GetDlgItem(IDC_BUTTON_LOGIN))->EnableWindow(FALSE); ((CEdit*)GetDlgItem(IDC_EDIT_MESSAGE))->EnableWindow(TRUE); break; case IDCANCEL: break; default: break; } } 编译项目并运行,单击登录按钮,看看运行情况。 二、服务器端 任务1:创建服务器框架程序,创建监听套接字并接受连接请求。 1. 在Chat工作区,用MFC AppWizard创建基于对话框的项目ChatServer,并在Step2中 选中Windows Socket选项。 2. 添加一个从CSocket类派生的CListenSocket类,为该类添加类型为CChatServerDlg*的 成员变量m_pDlg,并修改构造函数和析构函数如下:(声明类CchatServerDlg) CListenSocket::CListenSocket(CChatServerDlg* pDlg) { m_pDlg = pDlg; } CListenSocket::~CListenSocket() { m_pDlg = NULL; } 3. 为CChatServerDlg类添加类型为CListenSocket*的成员变量m_pListenSocket //在CchatServerDlg.h中包含ListenSocket.h 4. 在CChatServerDlg类的OnInitDialog()中添加如下代码: // TODO: Add extra initialization here m_pListenSocket = new CListenSocket(this); if(!m_pListenSocket->Create(8000)) { delete m_pListenSocket; m_pListenSocket = NULL; AfxMessageBox("创建套接字错误~"); return FALSE; } if(!m_pListenSocket->Listen()) { delete m_pListenSocket; m_pListenSocket = NULL; AfxMessageBox("启动监听错误~"); return FALSE; } 5. 为CListenSocket类添加虚函数OnAccept(),并添加如下代码: CSocket::OnAccept(nErrorCode); m_pDlg->OnAccept();//这有问题,m_pDlg是CchatServerDlg指针型没有OnAccept函数 6. 给项目添加CClientSocket类,该类从CSocket类派生,用于服务器与客户机进行消息 传输。给该类添加类型为CChatServerDlg*的成员变量m_pDlg,并修改构造函数和析构 函数如下:(注意,也应修改类声明中的构造函数原型) CClientSocket::CClientSocket(CChatServerDlg* pDlg) { m_pDlg = pDlg; } CClientSocket::~CClientSocket() { m_pDlg = NULL; } 7. 为CChatServerDlg类添加成员函数void OnAccept(void),并添加如下代码: CClientSocket* pSocket = new CClientSocket(this); m_pListenSocket->Accept(*pSocket); 编译项目,并运行服务器和客户机,试一试客户机是否能够连接服务器。//明显不能 任务3: 定义消息格式、消息类型,实现用户的登录。 图1 客户机/服务器之间的消息传输顺序图 表1 消息格式 序号 字段名 类型 长度 说明 1 type 整型 4字节 消息的类型 2 username 字符串 20字节 用户名 3 data 字符串 256字节 数据,如文字消息 表2 消息类型 序号 种类 说明 1 LOGIN_REQUEST 登录请求消息 2 LOGIN_SUCCESS 登录成功消息 3 LOGIN_FAILED 登录失败消息 4 LOGOUT_REQUEST 注销消息 5 ADD_USER 增加用户消息 6 REMOVE_USER 删除用户消息 7 PRIVATE_MESSAGE 私聊消息 8 PUBLIC_MESSAGE 群聊消息 连接并登录服务器的顺序图大致如下: 实现过程: 一、客户端 在客户端的对话框类的头文件中添加如下代码: 1( enum PROTO_TYPE // 消息类型定义 { LOGIN_REQUEST, LOGIN_SUCCESS, LOGIN_FAILED, LOGOUT_REQUEST, ADD_USER, REMOVE_USER, PRIVATE_CHAT, PUBLIC_CHAT }; typedef struct tagPacket // 数据包格式定义 { PROTO_TYPE type; char username[20]; char data[256]; } Packet; 2( 在CChatClientDlg::OnButtonLogin()中的case IDOK:下添加如下代码:(创建套接字,并 连接服务器。连接成功后创建登录数据包并发送至服务器) case IDOK: m_pMySocket = new CMySocket(this); if(!m_pMySocket->Create()) { delete m_pMySocket; m_pMySocket = NULL; AfxMessageBox("创建套接字失败~"); return; } if(!m_pMySocket->Connect(dlg.m_strIP, dlg.m_nPort)) { delete m_pMySocket; m_pMySocket = NULL; AfxMessageBox("连接服务器失败~"); return; } // 连接成功后发送登录数据包至服务器 Packet packet; memset(&packet, 0, sizeof(Packet)); packet.type = LOGIN_REQUEST; strcpy(packet.username, dlg.m_strUserName); strcpy(packet.data, dlg.m_strPassword); m_pMySocket->Send(&packet, sizeof(Packet)); break; 3( 在CMySocket类中重载OnReceive()函数,并添加如下代码:(当套接字收到数据包 时,MFC框架会调用该函数,而该函数在内部调用对话框的OnReceive()函数对接收 的数据包进行相应的处理) CSocket::OnReceive(nErrorCode); m_pDlg->OnReceive(); //这里需要在Mysocket.cpp上添加类和OnReceive函数的声明 4( 在CChatClientDlg类中添加void OnReceive(void)函数,接收服务器发送的数据包, 并根据数据包类型(在这里是登录成功数据包)进行相应处理。 Packet packet; memset(&packet, 0, sizeof(Packet)); m_pMySocket->Receive(&packet, sizeof(Packet)); switch(packet.type) { case LOGIN_SUCCESS: m_listMessage.AddString("login succeed."); ((CButton*)GetDlgItem(IDC_BUTTON_LOGOUT))->EnableWindow(TRUE); ((CButton*)GetDlgItem(IDC_BUTTON_LOGIN))->EnableWindow(FALSE); ((CEdit*)GetDlgItem(IDC_EDIT_MESSAGE))->EnableWindow(TRUE); break; } 5( 在服务器端的CChatServerDlg.h文件的开头添加如下的结构体,用于保存在线用户的名 称和对应的套接字指针,以实现一对一的聊天消息的转发: typedef struct tagUserInfo { char *username; CClientSocket* pSocket; } UserInfo; 二、服务器端 1( 在服务器端的对话框类的头文件中添加如下代码: enum PROTO_TYPE // 消息类型定义 { LOGIN_REQUEST, LOGIN_SUCCESS, LOGIN_FAILED, LOGOUT_REQUEST, ADD_USER, REMOVE_USER, PRIVATE_CHAT, PUBLIC_CHAT }; typedef struct tagPacket // 数据包格式定义 { PROTO_TYPE type; char username[20]; char data[256]; } Packet; 2( 在服务器端的CChatServerDlg类中添加类型为CPtrList类型的成员变量m_listUser,当 用户登录服务器之后,在该链表中添加用户的信息(指向UserInfo结构体类型的指针)。 3( 在重载CListenSocket类的OnAccept()函数,并添加如下代码: CSocket::OnAccept(nErrorCode); m_pDlg->OnAccept(); 4( 在CChatServerDlg类中添加(其实是编辑)void OnAccept(void)函数,在该函数中服务 器接收客户端的连接请求,生成该用户的UserInfo结构信息,并把该信息添加到 m_listUser链表中,具体代码如下: CClientSocket* pSocket = new CClientSocket(this); m_pListenSocket->Accept(*pSocket); UserInfo *pUserInfo = new UserInfo(); pUserInfo->pSocket = pSocket; m_listUser.AddHead(pUserInfo); 5( 在CClientSocket类中重载OnReceive()函数,并在该函数中调用CChatServerDlg类的 OnReceive()函数,代码如下: CSocket::OnReceive(nErrorCode); m_pDlg->OnReceive(this); 6( 在CChatServerDlg类中添加void OnR(void)函数,在该函数中服务器接收客户端发送的 数据包并根据数据包的类型进行相应处理(在这里是处理登录请求),其代码如下: Packet packet; memset(&packet, 0, sizeof(Packet)); pSocket->Receive(&packet, sizeof(Packet)); switch(packet.type) { case LOGIN_REQUEST: POSITION pos; for(pos = m_listUser.GetHeadPosition(); pos != NULL;) { UserInfo *pInfo = (UserInfo*)m_listUser.GetNext(pos); if(pInfo->pSocket == pSocket) { pInfo->username = packet.username; packet.type = LOGIN_SUCCESS; pSocket->Send(&packet, sizeof(Packet)); break; } } break; }
本文档为【MFC+Winsock类c_s聊天程序开发(略修改).doc】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
该文档来自用户分享,如有侵权行为请发邮件ishare@vip.sina.com联系网站客服,我们会及时删除。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。
本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。
网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
下载需要: 免费 已有0 人下载
最新资料
资料动态
专题动态
is_482581
暂无简介~
格式:doc
大小:111KB
软件:Word
页数:15
分类:
上传时间:2018-02-21
浏览量:13