Windows编程课程设计文档
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
桂林理工大学Windows编程课程设计
题目:MFC网络聊天室
2010年11月14日
一、需求分析
1.1功能描述
本项目是一个基于多线程网络聊天室,主要实现一般的聊天功能,就是不同用户之间的信息收发。
软件主要实现原理是采用UDP(面向无连接)协议,服
务器和客户端运行在同一个软件上,既软件本身既是服务器,也是客户端。
在不
同计算机上运行本程序,任意两台运行本软件的计算机就可以实现相互通信,实
现信息的转发。
本软件主要实现功能有两点:
1.实现服务器端秘客户端之间的通信。
2.显示系统时间。
1.2运行环境
在Visual studio 6.0WindowsOS平台
1.3开发工具
Visual studio 6.0MFC
1.4 MFC的消息实现机制
在MFC的框架结构下,可以进行消息处理的类的头文件里面都会含有
DECLARE_MESSAGE_MAP()宏,这里主要进行消息映射和消息处理函数的声明。
可以
进行消息处理的类的实现文件里一般都含有如下的结构。
BEGIN_MESSAGE_MAP(CInheritClass, CBaseClass)
//{{AFX_MSG_MAP(CInheritClass)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
这里主要进行消息映射的实现和消息处理函数的实现。
所有能够进行消息处理的类
都是基于CCmdTarget类的,也就是说CCmdTarget类是所有可以进行消息处理类的
父类。
CCmdTarget类是MFC处理命令消息的基础和核心。
二、项目设计
2.1设计原理
本项目主要采用面向无连接socket编程,实现原理如图1-1。
图1-1
2.2主要功能设计
本项目主要实现在的功能为运行本程序的任意两台计算机之间的消息通信,可以自由的发送和接收信息。
所以主要设计就是实现信息的发送和接收。
最终实现效果图如图1-2。
图1-2
2.3流程图
2.3设计步骤
2.3.1界面设计
本聊天程序实现工具为Visual C++ 6.0 MFC,主要利用其中用于网络编程的Socket类实现网络通讯功能。
程序只有一部分,其控件主要包括3个编缉框(IDC_EDIT_RECV、IDC_EDIT_SEND、IDC_EDIT_TIME)、两个静态文本框(IDC_STATIC_IP、IDC_STATIC_TIME)、两个组合框(IDC_STATIC_RECV、IDC_STATIC_SEND)、一个IP地址(IDC_IPADDRESS)、两个按钮(IDC_SEND、IDC_CANCEL)。
其最终界面如图1-3。
图1-3
2.3.2功能设计
⑴在CChatudpApp::InitInstance()应用程序内调用AfxSocketInit()对套接字进行初始化
BOOL CChatudpApp::InitInstance()
{
//加载套接字,进行版本协商
if(!AfxSocketInit())
{
AfxMessageBox("加载套接字失败!");
return false;
}
②在CChatudpDlg类添加InitSocket()来创建套接字
BOOL CChatudpDlg::InitSocket()
{
//创建一个基于数据报的套接字
m_socket=socket(AF_INET,SOCK_DGRAM,0);
if(INVALID_SOCKET==m_socket)
{
MessageBox("初始化套接字失败!");
return FALSE;
}
//定义Socket编程里用到的结构体,用sockaddr_in结构指定IP地址和端口信息
SOCKADDR_IN addrsock;
addrsock.sin_family=AF_INET;
addrsock.sin_port=htons(5000);
addrsock.sin_addr.S_un.S_addr=htonl(INADDR_ANY);
/*绑定套接字*/
int retval;
retval = bind(m_socket,(SOCKADDR*)&addrsock,sizeof(addrsock));
if(SOCKET_ERROR==retval)
{
closesocket(m_socket);
MessageBox("绑定失败!");
return false;
}
return TRUE;
}
⑶在CChatudpDlg::OnInitDialog()添加如下代码,用来为每个socket创建相对应的处理线程函数。
//定义一个计时器,每秒更新一次
SetTimer(0,1000,NULL);
//调用初始化套接字函数,并创建套接字
InitSocket();
//新建结构体变量
RECVPARAM *pRecvparam=new RECVPARAM;
//初始化变量
pRecvparam->sock=m_socket;
pRecvparam->hwnd=m_hWnd;
//创建进程
HANDLE hThread=CreateThread(NULL,0,RecvPro,(LPVOID)pRecvparam,0,NULL);
CloseHandle(hThread);//回收线程地址空间
⑷在CChatudpDlg类中添加线程函数RecvPro,主要用来处理每个用户的操作事件DWORD WINAPI CChatudpDlg::RecvPro(LPVOID lpParameter)
{
//取出套字接和窗口句柄
SOCKET sock=((RECVPARAM*)lpParameter)->sock;
HWND hwnd=((RECVPARAM*)lpParameter)->hwnd;
//定义一个网络地址结构变量
SOCKADDR_IN addrfrom;
int len=sizeof(SOCKADDR);
char Rebuf[200];
char tembuf[300];
int recvtal;
//使用循环来接收消息
while(true)
{
//调用接收函数来获取消息
recvtal=recvfrom(sock,Rebuf,200,0,(SOCKADDR*)&addrfrom,&len);
if(SOCKET_ERROR==recvtal)
break;
//格式化消息到tembuf
sprintf(tembuf,"来自%s说:%s",inet_ntoa(addrfrom.sin_addr),Rebuf);
//使用消息机制来传送消息,交给函数onRecvdata()处理
::PostMessage(hwnd,WM_RECVDATA,0,(LPARAM)tembuf);
}
return 0;
}
⑸消息接收函数并将消息显示到窗口
void CChatudpDlg::OnRecvdata(WPARAM wParam,LPARAM lParam)
{
//把接收到的消息付给str
CString str=(char*)lParam;
CString strtemp;
//得到接收编缉框的旧消息,
GetDlgItemText(IDC_EDIT_RECV,strtemp);
str+="\r\n";
str+=strtemp;
//显示接收到的信息
SetDlgItemText(IDC_EDIT_RECV,str);
}
⑹OnSend消息发送函数
void CChatudpDlg::OnSend()
{
// TODO: Add your control notification handler code here
//获取IP地址控件的值
DWORD ip;
((CIPAddressCtrl*)GetDlgItem(IDC_IPADDRESS))->GetAddress(ip);
if(CString(ip)=="")
{
MessageBox("请输入对方IP");
}
//定义Socket编程里用到的结构体,用sockaddr_in结构指定IP地址和端口信息SOCKADDR_IN sendd;
sendd.sin_family=AF_INET;
sendd.sin_port=htons(5000);
sendd.sin_addr.S_un.S_addr=htonl(ip);
CString strsend;
GetDlgItemText(IDC_EDIT_SEND,strsend);
//发送消息
sendto(m_socket,strsend,strsend.GetLength()+1,0,(SOCKADDR*)&sendd,sizeof(SOCKADDR));
SetDlgItemText(IDC_EDIT_SEND,"");
}
⑺获取系统时间函数
void CChatudpDlg::Time()
{
//获取当前系统日期和时间
CTime theTime=CTime::GetCurrentTime();
CString str;
//格式化日期时间。
这里的年月日时分秒的顺序随你排列,就是说theTime.GetYear(),theTime.GetMonth()
str.Format("%d-%d-%d %d:%d:%d",theTime.GetYear(),theTime.GetMonth(),
theTime.GetDay(),theTime.GetHour(),theTime.GetMinute(),
theTime.GetSecond());
//在编缉框显示日期和时间
SetDlgItemText(IDC_EDIT_TIME,str);
}
三、主要功能的测试方案与效果
将本程序拷至多台计算机上运行(要求要装有visual c++ 6.0的Windows OS平台上),在IP地址栏输入对方的IP地址就可以实现聊天功能。
测试给果如图1-4和图1-5。
图1-4
图1-5
四、程序的使用说明文档
此聊天程序的实现只有一个程序,所以使用比较简单,运行本程序服务器端可开启服务,就可能接收对方客户端发送的消息。
客户端通过IP地址栏填入服务器IP,既可向对方服务器发送消息,从而接入聊天网络,实现局域互通。
如分别在A、B机上运行Chatudp程序,A的IP在址为192.168.4.145、B的IP地址为192.168.4.146。
A要向B发送消息,要在IP地址栏填上B的IP(192.168.4.146)地址;B要向A发送也要先填上A的IP(192.168.4.145)地址。
五、结果及分析:
此程序的功能达到了之前预想的可能,通过服务器端的消息转发,实现了多用户之间的通信,实现了一个简单的网络聊天软件的功能。
通过此次的实验,也同时让我对于Socket 网络聊天类的使用有了更深入的了解,在关于网络编程的方面也有了新的认识。
虽然此程序的功能还比较的简单,而且某些方面还没能完善,但是,我相信我只是一个开始。
现在就软件自身还存在的问题罗列如下:
1、不能识别相同IP与相同昵称下的个人信息,在聊天过程中容易混乱;
2、用户登录前必须先知道服务器端的IP,这样操作显然比较麻烦;
3、程序界面做的比较单一,缺少层次性的美感。