MFC课程
设计
领导形象设计圆作业设计ao工艺污水处理厂设计附属工程施工组织设计清扫机器人结构设计
报告---聊天室程序设计.doc
河海大学计算机及信息工程学院(常州)
MFC
题 目 聊天室程序设计
学 号 20062325
专 业 计算机科学与技术
授课班号 243002
学生姓名 邓燕
指导教师 景雪琴老师
完成时间 2008.12.30
题目:设计一个聊天室系统,实现多人一起聊天。
一. 引言
1.1开发背景
随着网络信息时代的来临,INTERNET应用越来越广泛,人们越来越习惯于在网上获取和交流信息。据调查显示,80%以上的人上网都会打开聊天工具来聊天,而几乎每一个年轻人都会去聊天。使用网上聊天已经成为现代年轻人一种新的交往方式。聊天室更适合于陌生人之间进行较为主观、感兴化的讨论。所以有大部分的人会进入聊天室聊天,它会给人一个完全自由的聊天世界。因此我联系所学的MFC知识,决定做一个简易的聊天室程序。
1.2开发环境以及运行环境
1.2.1 开发环境
, Intel? Pentium? 4 2.0GHz,512M内存,80G硬盘
, Microsoft? Windows? XP Professional
, Microsoft? Visual C++ 6.0
1.2.2 运行环境
, Intel? Pentium? 2及以上处理器,32M以上内存,4G以上硬盘
, Microsoft? Windows? XP操作系统
, 800*600或以上的屏幕分辨率
二(需求分析
1、 用WINSOCK实现简单的网络聊天;
2、 在MFC开发平台上编写一个聊天系统;
3、 得server和client之间可以相互通信;
4、多人能够发送信息至服务器,首先显示进入聊天室的成员名,
然后显示对方名字和聊天信息,可以并发执行。 三、算法分析
建立连接过程流程图如下:
Server端Client端
创建CClientSocket
对象,在某个端口
提供监听服务
等待来自Client
端的服务请求创建CChatSocket对
象,向Server的监听
端口发出请求
接受Client端的请
建立连接求,用返回的
CClientSocket建立
连接
向用向用CChatSocket数据通路CClientSocket连连接建立的流中读接建立的流中读写数据写数据
关闭关闭CClientSocket,拆除链路CChatSocket,结结束与当前Client的束与当前Server端通信,等待其他请求的通信
关闭CClientSocket对
象,结束监听服务
四、详细设计
程序个模块代码如下:
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类的头文件开始处增加如下代码:
class CChatClientDlg; //主对话框类
(6)给ChatSocket类重载一个构造函数,其定义如下:
CChatSocket::CChatSocket(CChatClientDlg* pDlg)
{
m_pDlg = pDlg;
}
并且在ChatSocket类的CPP文件开始处增加如下语句:
#include "ChatClientDlg.h"
(7)通过ClassWizard响应类的ChatSocket的OnReceive函数,
表
关于同志近三年现实表现材料材料类招标技术评分表图表与交易pdf视力表打印pdf用图表说话 pdf
示可以接
收数据了,其代码如下:
//
通知
关于发布提成方案的通知关于xx通知关于成立公司筹建组的通知关于红头文件的使用公开通知关于计发全勤奖的通知
客户端可以接受数据
void CChatSocket::OnReceive(int nErrorCode) {
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类的头文件开始处增加如下代码:
class CChatSocket;//基于CSocket的新类CChatSocket
(9)给对话框CChatClientDlg增加处理接收数据的共有成员函数
ProcessPendingRead,其定义如下:
void CChatClientDlg::ProcessPendingRead()//处理接收的数据{
//定义缓冲区
char buffer[BUFFER_SIZE];
//接收数据
int nReceived = m_pSocket->Receive(buffer,BUFFER_SIZE,0);
buffer[nReceived] = 0;
//将数据在列表框中显示出来
CString str;
str.Format("%s",buffer);
m_ctrlMsgs.AddString(str);
}
(10)给对话框CChatClientDlg增加发送数据的私有成员函数SendMsg:
//发送数据到服务器
void CChatClientDlg::SendMsg(CString strMsg){
CString str;
str.Format("%s:%s",m_strClientName,strMsg);
m_pSocket->Send(str.GetBuffer(0),str.GetLength(),0);
}
并且在CChatClientDlg类的头文件开始处定义缓冲区的大小,其代码
如下:
#define BUFFER_SIZE 200
(11)给对话框CChatClientDlg增加表示聊天代号的CString类型私有成员
变量m_strClientName。
(12)在对话框CChatClientDlg的OnInitialUpdate函数中增加登录服务器
的代码:
BOOL CChatClientDlg::OnInitDialog()//登录服务器{
CDialog::OnInitDialog();
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL) {
CString strAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if (!strAboutMenu.IsEmpty()) {
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING,IDM_ABOUTBOX,
strAboutMenu);
}
}
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
//显示登录对话框
CSetupDlg dlg;
if(dlg.DoModal()==IDOK) {
//创建一个新的Socket
m_pSocket = new CChatSocket(this);
if (!m_pSocket->Create()) {
delete m_pSocket;
m_pSocket = NULL;
AfxMessageBox("create socket failed");
return FALSE;
}
//连接服务器
while (!m_pSocket->Connect(dlg.m_strServer,dlg.m_nPort + 700)) {
if (AfxMessageBox("Failed to connect to server\nTry
again?",MB_YESNO) == IDNO) {
delete m_pSocket;
m_pSocket = NULL;
return FALSE;
}
}
m_strClientName = dlg.m_strName;
}
else
return FALSE;
//发送登录消息给服务器
SendMsg("进入聊天室");
return TRUE; // return TRUE unless you set the focus to a control
}
(13)给主对话框CChatClientDlg增加一个CListBox类型的变量m_strMsg。
(14)给住对话框CChatClientDlg增加一个输入发送信息的编辑框,并生成
对应的CString类型的变量m_strMsg。
(15)给主对话框CChatClientDlg增加一个【send】按钮,其响应函数定义
如下:
void CChatClientDlg::OnSend() //响应控件send{
UpdateData(TRUE);
SendMsg(m_strMsg);
m_strMsg.Empty();////清空编辑区
UpdateData(FALSE);
}
(16)给主对话框增添一个【离开】按钮,其响应函数定义如下:
void CChatClientDlg::leave()//离开{
SendMsg("离开聊天室");
m_ctrlMsgs.AddString("离开状态");
m_pSocket->Close();
}
(17)给主对话框增添一个【连接】按钮,其响应函数如下:
void CChatClientDlg::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类的头文件开始处增加如下代码:
class CChatServerDlg; //主对话框类
(6)给ChatSocket类重载一个构造函数,其定义如下:
CChatSocket::CClientSocket(CChatServerDlg* pDlg)
{ m_pDlg = pDlg; }
并且在CListeningSocket类的CPP文件开始处增加如下语句:
#include "ChatServerDlg.h"
(7)通过ClassWizard响应类的CListeningSocket的OnAccept函数,表示
客户端连接,其代码如下:
void CListeningSocket::OnAccept(int nErrorCode)
//通知服务器,有客户端需要连接服务器
{ CSocket::OnAccept(nErrorCode);
//主对话框处理连接信息
if(m_pDlg)
m_pDlg->ProcessPendingAccept();
}
(8)通过ClassWizard生成基于CSocket的新类CClientSocket,用来与客
户端通信。
(9)给CClientSocket类声明一个主对话框CChatServerDlg指针类型的私有
成员变量,其代码如下:
protected:
CChatServerDlg* m_pDlg;
并且在CClientSocket类的头文件开始处增加如下语句:
class CChatServerDlg;
(10)给CClientSocket类重载一个构造函数,其定义如下:
CClientSocket::CClientSocket(CChatServerDlg* pDlg){
m_pDlg = pDlg;
}
并且在CClientSocket类的CPP文件开始处增加如下语句:
#include "ChatServerDlg.h" (11)通过ClassWizard响应类的CClientSocket的OnReceive函数,表示数
据已到达,其代码如下:
void CClientSocket::OnReceive(int nErrorCode)
//通知服务器可以接受数据
{ CSocket::OnReceive(nErrorCode);
if(m_pDlg)
{ //让主对话框处理数据
m_pDlg->ProcessPendingRead(this);
}
}
(12)在主对话框CChatServerDlg的头文件那个增加两个私有成员变量,其
代码如下:
CListeningSocket* m_pSocket; //监听套节字
CPtrList m_connectionList; //客户端套节字链表
并且在CChatSvrDlg的头文件开始处增加如下代码:
class CListeningSocket;
class CClientSocket;
(13)给主对话框CChatSvrDlg增加处理客户端连接信息的私有成员变量
ProcessPendingAccept,其定义如下:
void CChatServerDlg::ProcessPendingAccept() {
//生成一个新的套节字与客户端通讯
CClientSocket* pSocket = new CClientSocket(this);
if (m_pSocket->Accept(*pSocket)) {
//将该套节字保存起来
m_connectionList.AddTail(pSocket);
}
else
delete pSocket;
}
(14)给主对话框CChatSvrDlg增加更新所有客户端的私有成员函数
UpdateClient,其定义如下:
void CChatServerDlg::UpdateClients(char* buffer,int nBufferSize)
{
for(POSITION pos = m_connectionList.GetHeadPosition();
pos != NULL;)
{
//将新信息发送给每个客户端
CClientSocket* pSocket= (CClientSocket*)m_connectionList.GetNext(pos);
if (buffer != NULL)
pSocket->Send(buffer,nBufferSize,0);
}
}
(15)给主对话框CChatSvrDlg增加接受数据的私有成ProcessPendingRe,
其定义如下:
void CChatServerDlg::ProcessPendingRead(CClientSocket* pSocket)
{
//定义缓冲区
char buffer[BUFFER_SIZE];
//接收数据
int nReceived = pSocket->Receive(buffer,BUFFER_SIZE,0);
buffer[nReceived] = 0;
//将数据在列表框中显示出来
m_ctrlMsgs.AddString(buffer);
//将数据发送给每个客户
UpdateClients(buffer,nReceived);
}
并且在CChatSvrDlg类的头文件开始处定义缓冲区的大小,其代码如下:
#define BUFFER_SIZE 200
(16)给主对话框CChatSvrDlg的OnInitialUpdate函数中显示初始化对话框,
其定义如下:
BOOL CChatServerDlg::OnInitDialog()
{
CDialog::OnInitDialog();
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
CString strAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if (!strAboutMenu.IsEmpty())
{
->AppendMenu(MF_SEPARATOR); pSysMenu
pSysMenu->AppendMenu(MF_STRING,IDM_ABOUTBOX,
strAboutMenu);
}
}
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
//弹出初始话对话框
CInitDlg dlg;
if (dlg.DoModal() == IDOK)
{
//创建监听套节字
m_pSocket = new CListeningSocket(this);
if (m_pSocket->Create(dlg.m_nPort+700))
{
if (m_pSocket->Listen())
return TRUE;
}
else
return FALSE;
}
else
return FALSE;
return TRUE; // return TRUE unless you set the focus to a control
}
五、运行结果如下:
1.服务端初始化, 进入聊天室界面:
3.客户端初始化,端口号与服务器对应:
4. 进入聊天界面:
5.聊天室显示进入的客户:
6.另一个客户进入聊天室:
7.在客户界面上显示聊天界面:
(芳菲燕)
(卡罗)
8.在聊天室界面上显示所有客户的聊天
记录
混凝土 养护记录下载土方回填监理旁站记录免费下载集备记录下载集备记录下载集备记录下载
:
9.显示芳菲燕离开聊天室:
10.在芳菲燕的聊天界面上显示离开状态:
11.显示芳菲燕又进入聊天室:
六、课程设计心得:
我做的是“聊天室”系统,这个程序是和钟宏运同学合作的,他教会了我很多东西。通过做这个系统,我巩固和运用了很多课上学过的知识,也学会了很多课上没有讲过的知识,感受到了解课外知识的重要性,可谓是受益匪浅。
在最开始建立工程时就犯了一个很大的错误,间错了工程,以致在建类时总是出错,浪费了几个小时才发现要建基于对话框的程序。这就体现了上课听讲的重要性,由于一时的疏忽又很有可能造成无可挽回的错误。我们做的系统很小,如果这是一个巨大工程,犯了这样一个错误,那是致命的。但是,话说回来,这不叫浪费时间,我们要吃一堑长一智,下次要记住,做工程,从第一步就应该认认真真,踏
踏实实,避免出错。已进入工程,首先就做好了所有的界面设计。其中又遇到了很多困难。在插入位图时,要调整位图的大小,这是我不知道的,通过参考
书
关于书的成语关于读书的排比句社区图书漂流公约怎么写关于读书的小报汉书pdf
和讨论终于完成这一步。从中,我更加坚定了讨论的重要作用。 其次,代码部分很多很复杂,但是结构确是很清晰的。我想这应该是MFC的一个很大的优点。根据参考书上的讲解和自己的揣摩,我明白了整个算法的灵魂。
这个程序讲的是通信,互联网上关于聊天功能的工具非常多,但是其实现技术都是大同小异。我们做的这个系统是用WINSOCK实现的最简单的聊天,多人能够发送信息至服务器,服务器首先显示进入聊天室的成员名,然后显示对方名字和聊天信息,而且可以并发执行。把通信的思想转化成语言的过程,靠的是C++的基础。实现过程中犯了很多错误,真的很后悔基础功不牢固,现在就要付出更多的时间来弥补。最近有很多专业课的要做课程设计,每一次任务的完成,都会很有成就感,发现经验真的很宝贵。有些人,可以随口说出那些常用的函数,走了一条捷径,而不知道的人,就要花时间去找那个函数,或者说自己写代码来实现那个函数的功能。所以,从现在开始,我会认真面对每一次编程,即使是小程序,也一样能锻炼人。
到这,这个学期的MFC学习结束了,但对知识的追求还没有结束,我们会的只是知识海洋里的一瓢水,还有更多的东西需要我们去钻研。不能说自己会有多高的觉悟,但小小的收益是无可否认的。
最后,谢谢景老师本学期的精心教导~