MFC课程设计报告聊天室程序设计.docx
《MFC课程设计报告聊天室程序设计.docx》由会员分享,可在线阅读,更多相关《MFC课程设计报告聊天室程序设计.docx(19页珍藏版)》请在冰豆网上搜索。
![MFC课程设计报告聊天室程序设计.docx](https://file1.bdocx.com/fileroot1/2022-11/20/250fa7dd-cf60-4044-9cfd-998ba5f3ad0b/250fa7dd-cf60-4044-9cfd-998ba5f3ad0b1.gif)
MFC课程设计报告聊天室程序设计
MFC课程设计报告
题目聊天室程序设计
学号
专业计算机科学与技术
授课班号
学生姓名
指导教师
完成时间2008.12.30
题目:
设计一个聊天室系统,实现多人一起聊天。
一.引言
1.1开发背景
随着网络信息时代的来临,INTERNET应用越来越广泛,人们越来越习惯于在网上获取和交流信息。
据调查显示,80%以上的人上网都会打开聊天工具来聊天,而几乎每一个年轻人都会去聊天。
使用网上聊天已经成为现代年轻人一种新的交往方式。
聊天室更适合于陌生人之间进行较为主观、感兴化的讨论。
所以有大部分的人会进入聊天室聊天,它会给人一个完全自由的聊天世界。
因此我联系所学的MFC知识,决定做一个简易的聊天室程序。
1.2开发环境以及运行环境
1.2.1 开发环境
●Intel®Pentium®42.0GHz,512M内存,80G硬盘
●Microsoft®Windows™XPProfessional
●Microsoft®VisualC++6.0
1.2.2 运行环境
●Intel®Pentium®2及以上处理器,32M以上内存,4G以上硬盘
●Microsoft®Windows™XP操作系统
●800*600或以上的屏幕分辨率
二.需求分析
1、用WINSOCK实现简单的网络聊天;
2、在MFC开发平台上编写一个聊天系统;
3、得server和client之间可以相互通信;
4、多人能够发送信息至服务器,首先显示进入聊天室的成员名,然后显示对方名字和聊天信息,可以并发执行。
三、算法分析
建立连接过程流程图如下:
四、详细设计
程序个模块代码如下:
1.客户端
(1)通过AppWizard生成基于对话框的应用程序ChatClient,在向导的第二步选择WindowsSockets的支持,其余步骤均用默认值。
(2)增加一个登录服务器的对话框资源,其ID为IDD_SETUP,然后通过ClassWizard生成对应的基于CDialog的类CSetupDlg。
(3)给对话框CSetupDlg增加3个编辑框,用来输入登录信息(聊天代号、服务器地址以及服务器端口号),
(4)通过ClassWizard生成对应的基于CSocket的类CChatSocket。
(5)给CChatSocket类声明一个主对话框CChatClientDlg指针类型的私有成员变量,其代码如下:
protected:
CChatClientDlg*m_pDlg;
并且在ChatSocket类的头文件开始处增加如下代码:
classCChatClientDlg;//主对话框类
(6)给ChatSocket类重载一个构造函数,其定义如下:
CChatSocket:
:
CChatSocket(CChatClientDlg*pDlg)
{
m_pDlg=pDlg;
}
并且在ChatSocket类的CPP文件开始处增加如下语句:
#include"ChatClientDlg.h"
(7)通过ClassWizard响应类的ChatSocket的OnReceive函数,表示可以接收数据了,其代码如下:
//通知客户端可以接受数据
voidCChatSocket:
:
OnReceive(intnErrorCode){
CSocket:
:
OnReceive(nErrorCode);
if(m_pDlg){
PlaySound("F:
\msg.wav",NULL,SND_ASYNC|SND_NODEFAULT);
m_pDlg->ProcessPendingRead();
}
}
(8)在主对话框ChatClientDlg的头文件中定义ChatSocket指针类型的私有成员变量,其代码如下:
CChatSocket*m_pSocket;
并且在CChatClientDlg类的头文件开始处增加如下代码:
classCChatSocket;//基于CSocket的新类CChatSocket
(9)给对话框CChatClientDlg增加处理接收数据的共有成员函数ProcessPendingRead,其定义如下:
voidCChatClientDlg:
:
ProcessPendingRead()//处理接收的数据{
//定义缓冲区
charbuffer[BUFFER_SIZE];
//接收数据
intnReceived=m_pSocket->Receive(buffer,BUFFER_SIZE,0);
buffer[nReceived]=0;
//将数据在列表框中显示出来
CStringstr;
str.Format("%s",buffer);
m_ctrlMsgs.AddString(str);
}
(10)给对话框CChatClientDlg增加发送数据的私有成员函数SendMsg:
//发送数据到服务器
voidCChatClientDlg:
:
SendMsg(CStringstrMsg){
CStringstr;
str.Format("%s:
%s",m_strClientName,strMsg);
m_pSocket->Send(str.GetBuffer(0),str.GetLength(),0);
}
并且在CChatClientDlg类的头文件开始处定义缓冲区的大小,其代码如下:
#defineBUFFER_SIZE200
(11)给对话框CChatClientDlg增加表示聊天代号的CString类型私有成员变量m_strClientName。
(12)在对话框CChatClientDlg的OnInitialUpdate函数中增加登录服务器的代码:
BOOLCChatClientDlg:
:
OnInitDialog()//登录服务器{
CDialog:
:
OnInitDialog();
ASSERT((IDM_ABOUTBOX&0xFFF0)==IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX<0xF000);
CMenu*pSysMenu=GetSystemMenu(FALSE);
if(pSysMenu!
=NULL){
CStringstrAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if(!
strAboutMenu.IsEmpty()){
pSysMenu->AppendMenu(MF_SEPARATOR);pSysMenu->AppendMenu(MF_STRING,IDM_ABOUTBOX,strAboutMenu);
}
}
SetIcon(m_hIcon,TRUE);//Setbigicon
SetIcon(m_hIcon,FALSE);//Setsmallicon
//显示登录对话框
CSetupDlgdlg;
if(dlg.DoModal()==IDOK){
//创建一个新的Socket
m_pSocket=newCChatSocket(this);
if(!
m_pSocket->Create()){
deletem_pSocket;
m_pSocket=NULL;
AfxMessageBox("createsocketfailed");
returnFALSE;
}
//连接服务器
while(!
m_pSocket->Connect(dlg.m_strServer,dlg.m_nPort+700)){
if(AfxMessageBox("Failedtoconnecttoserver\nTryagain?
",MB_YESNO)==IDNO){
deletem_pSocket;
m_pSocket=NULL;
returnFALSE;
}
}
m_strClientName=dlg.m_strName;
}
else
returnFALSE;
//发送登录消息给服务器
SendMsg("进入聊天室");
returnTRUE;//returnTRUEunlessyousetthefocustoacontrol
}
(13)给主对话框CChatClientDlg增加一个CListBox类型的变量m_strMsg。
(14)给住对话框CChatClientDlg增加一个输入发送信息的编辑框,并生成对应的CString类型的变量m_strMsg。
(15)给主对话框CChatClientDlg增加一个【send】按钮,其响应函数定义如下:
voidCChatClientDlg:
:
OnSend()//响应控件send{
UpdateData(TRUE);
SendMsg(m_strMsg);
m_strMsg.Empty();////清空编辑区
UpdateData(FALSE);
}
(16)给主对话框增添一个【离开】按钮,其响应函数定义如下:
voidCChatClientDlg:
:
leave()//离开{
SendMsg("离开聊天室");
m_ctrlMsgs.AddString("离开状态");
m_pSocket->Close();
}
(17)给主对话框增添一个【连接】按钮,其响应函数如下:
voidCChatClientDlg:
:
land()//连接{
OnInitDialog();
}
2.服务器端
(1)通过AppWizard生成基于对话框的应用程序ChatServer,在向导的第二步选择WindowsSockets的支持,其余步骤均用默认值。
(2)增加一个登录服务器的对话框资源,其ID为IDD_INT,然后通过ClassWizard生成对应的基于CDialog的类CInitDlg。
(3)给对话框CInitDlg增加1个输入端口号的编辑框,并生成对应的整形变量m_nPort。
(4)通过ClassWizard生成对应的基于CSocket的类CListeningSocket,用来监听服务器。
(5)给CListeningSocket类声明一个主对话框CChatServerDlg指针类型的私有成员变量,其代码如下:
protected:
CChatServerDlg*m_pDlg;
并且在CListeningSocket类的头文件开始处增加如下代码:
classCChatServerDlg;//主对话框类
(6)给ChatSocket类重载一个构造函数,其定义如下:
CChatSocket:
:
CClientSocket(CChatServerDlg*pDlg)
{m_pDlg=pDlg;}
并且在CListeningSocket类的CPP文件开始处增加如下语句:
#include"ChatServerDlg.h"
(7)通过ClassWizard响应类的CListeningSocket的OnAccept函数,表示客户端连接,其代码如下:
voidCListeningSocket:
:
OnAccept(intnErrorCode)
//通知服务器,有客户端需要连接服务器
{CSocket:
:
OnAccept(nErrorCode);
//主对话框处理连接信息
if(m_pDlg)
m_pDlg->ProcessPendingAccept();
}
(8)通过ClassWizard生成基于CSocket的新类CClientSocket,用来与客户端通信。
(9)给CClientSocket类声明一个主对话框CChatServerDlg指针类型的私有成员变量,其代码如下:
protected:
CChatServerDlg*m_pDlg;
并且在CClientSocket类的头文件开始处增加如下语句:
classCChatServerDlg;
(10)给CClientSocket类重载一个构造函数,其定义如下:
CClientSocket:
:
CClientSocket(CChatServerDlg*pDlg){
m_pDlg=pDlg;
}
并且在CClientSocket类的CPP文件开始处增加如下语句:
#include"ChatServerDlg.h"
(11)通过ClassWizard响应类的CClientSocket的OnReceive函数,表示数据已到达,其代码如下:
voidCClientSocket:
:
OnReceive(intnErrorCode)
//通知服务器可以接受数据
{CSocket:
:
OnReceive(nErrorCode);
if(m_pDlg)
{//让主对话框处理数据
m_pDlg->ProcessPendingRead(this);
}
}
(12)在主对话框CChatServerDlg的头文件那个增加两个私有成员变量,其代码如下:
CListeningSocket*m_pSocket;//监听套节字
CPtrListm_connectionList;//客户端套节字链表
并且在CChatSvrDlg的头文件开始处增加如下代码:
classCListeningSocket;
classCClientSocket;
(13)给主对话框CChatSvrDlg增加处理客户端连接信息的私有成员变量ProcessPendingAccept,其定义如下:
voidCChatServerDlg:
:
ProcessPendingAccept(){
//生成一个新的套节字与客户端通讯
CClientSocket*pSocket=newCClientSocket(this);
if(m_pSocket->Accept(*pSocket)){
//将该套节字保存起来
m_connectionList.AddTail(pSocket);
}
else
deletepSocket;
}
(14)给主对话框CChatSvrDlg增加更新所有客户端的私有成员函数UpdateClient,其定义如下:
voidCChatServerDlg:
:
UpdateClients(char*buffer,intnBufferSize)
{
for(POSITIONpos=m_connectionList.GetHeadPosition();
pos!
=NULL;)
{
//将新信息发送给每个客户端
CClientSocket*pSocket=(CClientSocket*)m_connectionList.GetNext(pos);
if(buffer!
=NULL)
pSocket->Send(buffer,nBufferSize,0);
}
}
(15)给主对话框CChatSvrDlg增加接受数据的私有成ProcessPendingRe,
其定义如下:
voidCChatServerDlg:
:
ProcessPendingRead(CClientSocket*pSocket)
{
//定义缓冲区
charbuffer[BUFFER_SIZE];
//接收数据
intnReceived=pSocket->Receive(buffer,BUFFER_SIZE,0);
buffer[nReceived]=0;
//将数据在列表框中显示出来
m_ctrlMsgs.AddString(buffer);
//将数据发送给每个客户
UpdateClients(buffer,nReceived);
}
并且在CChatSvrDlg类的头文件开始处定义缓冲区的大小,其代码如下:
#defineBUFFER_SIZE200
(16)给主对话框CChatSvrDlg的OnInitialUpdate函数中显示初始化对话框,其定义如下:
BOOLCChatServerDlg:
:
OnInitDialog()
{
CDialog:
:
OnInitDialog();
ASSERT((IDM_ABOUTBOX&0xFFF0)==IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX<0xF000);
CMenu*pSysMenu=GetSystemMenu(FALSE);
if(pSysMenu!
=NULL)
{
CStringstrAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if(!
strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);pSysMenu->AppendMenu(MF_STRING,IDM_ABOUTBOX,strAboutMenu);
}
}
SetIcon(m_hIcon,TRUE);//Setbigicon
SetIcon(m_hIcon,FALSE);//Setsmallicon
//弹出初始话对话框
CInitDlgdlg;
if(dlg.DoModal()==IDOK)
{
//创建监听套节字
m_pSocket=newCListeningSocket(this);
if(m_pSocket->Create(dlg.m_nPort+700))
{
if(m_pSocket->Listen())
returnTRUE;
}
else
returnFALSE;
}
else
returnFALSE;
returnTRUE;//returnTRUEunlessyousetthefocustoacontrol
}
五、运行结果如下:
1.服务端初始化,进入聊天室界面:
3.客户端初始化,端口号与服务器对应:
4.进入聊天界面:
5.聊天室显示进入的客户:
6.另一个客户进入聊天室:
7.在客户界面上显示聊天界面:
(芳菲燕)
(卡罗)
8.在聊天室界面上显示所有客户的聊天记录:
9.显示芳菲燕离开聊天室:
10.在芳菲燕的聊天界面上显示离开状态:
11.显示芳菲燕又进入聊天室:
六、课程设计心得:
我做的是“聊天室”系统,这个程序是和钟宏运同学合作的,他教会了我很多东西。
通过做这个系统,我巩固和运用了很多课上学过的知识,也学会了很多课上没有讲过的知识,感受到了解课外知识的重要性,可谓是受益匪浅。
在最开始建立工程时就犯了一个很大的错误,间错了工程,以致在建类时总是出错,浪费了几个小时才发现要建基于对话框的程序。
这就体现了上课听讲的重要性,由于一时的疏忽又很有可能造成无可挽回的错误。
我们做的系统很小,如果这是一个巨大工程,犯了这样一个错误,那是致命的。
但是,话说回来,这不叫浪费时间,我们要吃一堑长一智,下次要记住,做工程,从第一步就应该认认真真,踏踏实实,避免出错。
已进入工程,首先就做好了所有的界面设计。
其中又遇到了很多困难。
在插入位图时,要调整位图的大小,这是我不知道的,通过参考书和讨论终于完成这一步。
从中,我更加坚定了讨论的重要作用。
其次,代码部分很多很复杂,但是结构确是很清晰的。
我想这应该是MFC的一个很大的优点。
根据参考书上的讲解和自己的揣摩,我明白了整个算法的灵魂。
这个程序讲的是通信,互联网上关于聊天功能的工具非常多,但是其实现技术都是大同小异。
我们做的这个系统是用WINSOCK实现的最简单的聊天,多人能够发送信息至服务器,服务器首先显示进入聊天室的成员名,然后显示对方名字和聊天信息,而且可以并发执行。
把通信的思想转化成语言的过程,靠的是C++的基础。
实现过程中犯了很多错误,真的很后悔基础功不牢固,现在就要付出更多的时间来弥补。
最近有很多专业课的要做课程设计,每一次任务的完成,都会很有成就感,发现经验真的很宝贵。
有些人,可以随口说出那些常用的函数,走了一条捷径,而不知道的人,就要花时间去找那个函数,或者说自己写代码来实现那个函数的功能。
所以,从现在开始,我会认真面对每一次编程,即使是小程序,也一样能锻炼人。
到这,这个学期的MFC学习结束了,但对知识的追求还没有结束,我们会的只是知识海洋里的一瓢水,还有更多的东西需要我们去钻研。
不能说自己会有多高的觉悟,但小小的收益是无可否认的。
最后,谢谢景老师本学期的精心教导!