ImageVerifierCode 换一换
格式:DOCX , 页数:16 ,大小:142.78KB ,
资源ID:6048802      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/6048802.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(MFC+Winsock类cs聊天程序开发.docx)为本站会员(b****6)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

MFC+Winsock类cs聊天程序开发.docx

1、MFC+Winsock类cs聊天程序开发案例开发和分析聊天程序的开发一、客户端任务1:创建客户端框架程序,设计用户界面,并实现和服务器的连接。1. 创建一个空白工作区,并命名为Chat。2. 在Chat工作区,用MFC AppWizard创建基于对话框的项目ChatClient,并在Step2中选中Windows Socket选项。3. 在对话框中添加控件,如下图所示:4. 对话框中的控件属性如下表:表1 控件属性控件类型控件IDCaption其他List BoxIDC_LIST_MESSAGE不选SortList BoxIDC_LIST_ONLINE_USERS不选SortEdit BoxI

2、DC_EDIT_MESSAGE选中Multiline和VerticalScrollRadio ButtonIDC_RADIO_GROUP群聊Radio ButtonIDC_RADIO_PRIVATE私聊ButtonIDC_BUTTON_LOGIN登录ButtonIDC_BUTTON_LOGOUT退出5. 用ClassWizard为控件对象定义相应的成员变量,如下表所示:表2 控件对应成员变量控件ID控件类型成员变量名IDC_EDIT_MESSAGECStringm_strMessageIDC_LIST_MESSAGECListBoxm_listMessageIDC_LIST_ONLINE_US

3、ERSCListBoxm_listUsers6. 添加对话框,ID为IDD_DIALOG_LOGIN,Caption为“登录”。7. 在对话框中添加控件,如下图所示:8. 对话框中的控件属性如下:表3 登录对话框控件属性控件类型控件IDCaption其他Edit BoxIDC_EDIT_IPEdit BoxIDC_EDIT_PORTEdit BoxIDC_EDIT_USERNAMEEdit BoxIDC_EDIT_PASSWORD选Styles-PasswordButtonIDOK连接选Styles-Default ButtonButtonIDCANCEL取消9. 添加一个新类,类名为CLog

4、inDlg,基类为CDialog,Dialog ID为IDD_DIALOG_LOGIN。10. 用ClassWizard为对话框的控件对象定义成员变量,如下表所示:表4 登录对话框控件对应成员变量控件ID控件类型成员变量名IDC_EDIT_IPCStringm_strIPIDC_EDIT_PASSWORDCStringm_strPasswordIDC_EDIT_PORTUINTm_nPortIDC_EDIT_USERNAMECStringm_strUserName11. 为CChatClientDlg类添加“登录”按钮的单击事件消息处理函数OnButtonLogin(),并添加如下代码: CL

5、oginDlg dlg; int nRet = -1; nRet = dlg.DoModal();12. 在ChatClientDlg.cpp中添加:#include LoginDlg.h 。编译项目并运行,单击登录按钮,看看运行情况。此时单击退出按钮无反应,tell me why?13. 添加一个从CSocket类派生的新类CMySocket,添加类型为CChatClientDlg*的成员变量m_pDlg, 并修改默认构造函数和析构函数如下:(注意,也应修改类声明中的构造函数原型)CMySocket:CMySocket(CChatClientDlg *pDlg) m_pDlg = pDlg;

6、CMySocket:CMySocket() m_pDlg = NULL; 在CMySocket类的头文件中,添加前置声明: class CChatClientDlg; 。14. 为CChatClientDlg类添加类型为CMySocket*的成员变量m_pMySocket,类型为BOOL的成员变量m_bGroupChat。在CChatClientDlg类的头文件中,添加前置声明: class CMySocket; 。15. /在CChatClientDlg:OnInitDialog()中添加如下代码:/ TODO: Add extra initialization herem_bGroupCh

7、at = TRUE; / 默认聊天方式为群聊(CButton*)GetDlgItem(IDC_RADIO_GROUP)-SetCheck(TRUE); / 设置群聊按钮被选中(CButton*)GetDlgItem(IDC_BUTTON_LOGOUT)-EnableWindow(FALSE); (CEdit*)GetDlgItem(IDC_EDIT_MESSAGE)-EnableWindow(FALSE); /设置编辑框不可用16. 在CChatClientDlg类的OnButtonLogin()中添加如下代码:void CChatClientDlg:OnButtonLogin() / TOD

8、O: 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_s

9、trIP, 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; de

10、fault: break; 在CChatClientDlg类的实现文件中,包含CMySocket类的头文件,即:#include MySocket.h。编译项目并运行,单击登录按钮,看看运行情况。注意:C+头文件不能相互包含,详情可参考以下链接 二、服务器端任务1:创建服务器框架程序,创建监听套接字并接受连接请求。1. 在Chat工作区,用MFC AppWizard创建基于对话框的项目ChatServer,并在Step2中选中Windows Socket选项。2. 添加一个从CSocket类派生的CListenSocket类,为该类添加类型为CChatServerDlg*的成员变量m_pDlg

11、,并修改构造函数和析构函数如下:(注意,也应修改类声明中的构造函数原型)CListenSocket:CListenSocket(CChatServerDlg* pDlg) m_pDlg = pDlg;CListenSocket:CListenSocket() m_pDlg = NULL;在类CListenSocket的头文件中,添加前置声明: class CChatServerDlg; 。3. 为CChatServerDlg类添加类型为CListenSocket*的成员变量m_pListenSocket在类CChatServerDlg的头文件中,添加前置声明: class CListenSoc

12、ket; 。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_pListenSocke

13、t; m_pListenSocket = NULL; AfxMessageBox(启动监听错误!); return FALSE; 在CChatServerDlg类的实现文件中,包含CListenSocket类的头文件,即:#include ListenSocket.h 。5. 给项目添加CClientSocket类,该类从CSocket类派生,用于服务器和客户机进行消息传输。给该类添加类型为CChatServerDlg*的成员变量m_pDlg,并修改构造函数和析构函数如下:(注意,也应修改类声明中的构造函数原型)CClientSocket:CClientSocket(CChatServerDl

14、g* pDlg) m_pDlg = pDlg;CClientSocket:CClientSocket() m_pDlg = NULL;在类CClientSocket的头文件中,添加前置声明: class CChatServerDlg; 。6. 为CChatServerDlg类添加类型为CClientSocket*的成员变量m_pClientSocket在类CChatServerDlg的头文件中,添加前置声明: class CClientSocket; 。7. 为CChatServerDlg类添加成员函数void OnAccept(void),并添加如下代码: CClientSocket* pS

15、ocket = new CClientSocket(this); m_pListenSocket-Accept(*pSocket);在CChatServerDlg类的实现文件中,包含CClientSocket类的头文件,即:#include ClientSocket.h8. 为CListenSocket类添加虚函数OnAccept(),并添加如下代码: CSocket:OnAccept(nErrorCode); m_pDlg-OnAccept();在CListenSocket类的实现文件中,包含CChatServerDlg类的头文件,即:#include ChatServerDlg.h编译项目

16、,并运行服务器和客户机,试一试客户机是否能够连接服务器。任务3:定义消息格式、消息类型,实现用户的登录。图1 客户机/服务器之间的消息传输顺序图表1 消息格式序号字段名类型长度说明1type整型4字节消息的类型2username字符串20字节用户名3data字符串256字节数据,如文字消息表2 消息类型序号种类说明1LOGIN_REQUEST登录请求消息2LOGIN_SUCCESS登录成功消息3LOGIN_FAILED登录失败消息4LOGOUT_REQUEST注销消息5ADD_USER增加用户消息6REMOVE_USER删除用户消息7PRIVATE_MESSAGE私聊消息8PUBLIC_MES

17、SAGE群聊消息连接并登录服务器的顺序图大致如下:实现过程:一、客户端1 在客户端的对话框类CChatClientDlg的头文件中添加如下代码: 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 username20; char data256; Packet;2 在

18、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_

19、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 在CChatClientDlg类中

20、添加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)

21、; (CButton*)GetDlgItem(IDC_BUTTON_LOGIN)-EnableWindow(FALSE); (CEdit*)GetDlgItem(IDC_EDIT_MESSAGE)-EnableWindow(TRUE); break; 4 在CMySocket类中重载OnReceive()函数,并添加如下代码:(当套接字收到数据包时,MFC框架会调用该函数,而该函数在内部调用对话框的OnReceive()函数对接收的数据包进行相应的处理) CSocket:OnReceive(nErrorCode); m_pDlg-OnReceive();在CMySocket类的实现文件中,包含

22、CChatClientDlg类的头文件,即:#include ChatClientDlg.h5 在服务器端的CChatServerDlg类的头文件的开头添加如下的结构体,用于保存在线用户的名称和对应的套接字指针,以实现一对一的聊天消息的转发: typedef struct tagUserInfo char *username; CClientSocket* pSocket; UserInfo;在CChatServerDlg类的头文件中,添加前置声明: class CClientSocket; 。二、服务器端1 在服务器端的对话框类CChatServerDlg的头文件中添加如下代码:enum P

23、ROTO_TYPE / 消息类型定义 LOGIN_REQUEST, LOGIN_SUCCESS, LOGIN_FAILED, LOGOUT_REQUEST, ADD_USER, REMOVE_USER, PRIVATE_CHAT, PUBLIC_CHAT;typedef struct tagPacket / 数据包格式定义 PROTO_TYPE type; char username20; char data256; Packet;2 在服务器端的CChatServerDlg类中添加类型为CPtrList类型的成员变量m_listUser,当用户登录服务器之后,在该链表中添加用户的信息(指向U

24、serInfo结构体类型的指针)。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(*

25、pSocket); UserInfo *pUserInfo = new UserInfo(); pUserInfo-pSocket = pSocket; m_listUser.AddHead(pUserInfo);5 在CClientSocket类中重载OnReceive()函数,并在该函数中调用CChatServerDlg类的OnReceive()函数,代码如下: CSocket:OnReceive(nErrorCode); m_pDlg-OnReceive();在CClientSocket类的实现文件中,包含CChatServerDlg类的头文件,即:#include ChatServer

26、Dlg.h6 在CChatServerDlg类中添加void OnReceive (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;

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1