湖南工业大学
课程设计任务书
2011——2012 学年第 1 学期
计算机与通信 学院(系、部) 通信
工程
路基工程安全技术交底工程项目施工成本控制工程量增项单年度零星工程技术标正投影法基本原理
专业 班级
课程名称: C++面向对象程序设计
设计题目: 简单网络聊天
完成期限:自 2011 年 12 月 19 日至 2011 年 12 月 24 日共 1 周
内
容
及
任
务
该系统
要求
对教师党员的评价套管和固井爆破片与爆破装置仓库管理基本要求三甲医院都需要复审吗
完成聊天室的全过程,包括客户端和服务器两大部分的编程及其连接。服务器端聊天程序负责接收和发送来自客户端的聊天信息,客户端聊天程序负责建立和维护与服务器端的连接,想服务器发送本客户的聊天内容。系统采用VISUAL C++语言程序设计编程实现。
此次课程设计的功能要求:在服务器和多个客户端之间进行数据传输;接收客户端发送的消息,并显示在一个列
表
关于同志近三年现实表现材料材料类招标技术评分表图表与交易pdf视力表打印pdf用图表说话 pdf
框中;发送信息时可以显示聊天的所有记录。
进
度
安
排
起止日期
工作内容
2011年12月19日
学习MFC编程的基础知识并能编写一些小的程序。
2011年12月20—21日
学习网络通信知识,理解CAsyncSocket和CSocket类。
2011年12月22日
通过前面的学习,并结合前面的一些小程序,综合编程。
2011年12月23日
运行并调试程序,出错的改错,没错的优化。
2011年12月24日
进行答辩和文档的编写。
主
要
参
考
资
料
[1]任泰明著,《TCP/IP协议与网络编》 西安:西安电子科技大学出版社,2004
[2]王建华等译,《Visual C++ 6.0 编程技术内幕》机械工业出版社 2001
[3]木林森、高峰霞等编著,《Visual C++6.0使用与开发》北京:清华大学出版社 2002
[4]张荣梅、梁晓林著,《Visual c++ 实用教程》,重庆:冶金工业出版社,2001
[5]谭浩强著,《Visual C++ 面向对象过程设计》,北京:清华大学出版社,2011
指导教师(签字): 年 月 日
系(教研室)主任(签字): 年 月 日
面向对象程序设计(C++)课程设计
设计说明书
简单网络聊天
起止日期: 2011 年 12 月 19 日 至 2011 年 12 月 24 日
学生姓名
班级
学号
成绩
指导教师(签字)
计算机与通信学院
2011年 12 月 25 日
1 引 言
1.1课题背景及意义
当今世界正处于信息时代,计算机和通信网络是这一时代所谓“信息基础设施”。在互联网相当普及的今天,在互联网上聊天对很多“网虫”来说已经是家常便饭了。聊天室程序可以说是网上最简单的多点通信程序。一个简单的聊天室, 从程序员的观点来看就是在多个I/O端点之间实现多对多的通信。基于SOCKET的局域网通信是一种灵活的、易于实现的、低成本的方法。它可以运行在各种使用TCP/IP协议作为通讯协议的网络上。而在SOCKET API的帮助下,开发基于SOCKET的局域网通信软件也是易于实现的。
1.2 实验平台介绍
Visual C++(简称VC)是Microsoft公司推出的目前使用极为广泛的基于Windows平台的C++可视化开发环境。VC基于C,C++语言,主要由是MFC组成,是与系统联系非常紧密的编程工具,它兼有高级,和低级语言的双重性,功能强大,灵活,执行效率高,几乎可说VC在 Windows平台无所不能。VC主要是针对Windows系统,适合一些系统级 的开发,可以方便实现一些底层 的调用。在VC里边嵌入汇编语言很简单。当对系统性能要求很高的时候,可用VC开发。VC在多线程、网络通信、分布应用方面,有着不可比拟的优势。
2需求分析
2.1 设计目的
面向对象程序设计是计算机科学与技术专业实践性环节之一,是学习完《面向对象程序设计》课程后进行的一次全面的综合练习。其目的在于加深对面向对象理论和基本知识的理解,掌握使用C++语言进行面向对象程序设计的基本方法,提高运用面向对象知识解决实际问题的能力。
使学生通过学习掌握C++语言的语法规则、面向对象的程序设计方法,对面向对象方法和思想增加感性的认识;学会利用VC++语言编写出一些具有一定功能的实用程序,切实提高面向对象的程序设计能力。
2.2 设计要求
采用客户/服务器模式,分为客户端程序和服务器端程序。服务器采用WINSOCK I/O模型中的任一种,支持多个客户同时在线聊天。客户端程序和服务器程序通过网络交换聊天字符串内容,服务器窗口的列表框中显示当前在线用户,支持客户端之间的私聊(可以通过服务器中转,或考虑UDP打洞直接建立端端连接)。
课程设计要求设计并编程完成两个方面的内容:首先建立一个使用TCP协议的聊天室服务器,这个服务器可以同时支持多个用户的在线聊天;其次设计一个可以和服务器通信的聊天室客户端。
2.3 通信分析
随着计算机网络的普及和Internet的迅速发展,越来越多的程序具备了网上与其它程序通信的能力。无论是在局域网还是广域网,软件的通信都采取同样的原则。类似如下图:(TCP/IP)
图1通信连接过程
首先,一台计算机中某个程序等带领一个程序的连接请求,这个应用程序正在“监听”种种连接请求,就像你在等待某人来电话时守在电话机旁一样。同时,另一个应用程序试图与第一个程序连接。这种打开连接的做法与你打电话类似。就像在打电话时你必须知道对方的电话号码一样,应用程序要建立连接也必须知道对方网络地址。
套接子,就等于是把端口,ip等网络接口这功能和在一起的一个网络编程接口。通过他从逻辑的角度简化了通讯的接口。应用程序执行大多数网络通信的基本对象称为套接口或软插口。这样套接口通过下面的方法工作,事实上我们的程序也是类似这么做的。
2.4 CAsyncSocket和CSocket
它是一个异步非阻塞Socket封装类,CAsyncSocket::Create()有一个参数指明了你想要处理哪些Socket事件,你关心的事件被指定以后,这个Socket默认就被用作了异步方式。CAsyncSocket的Create()函数,除了创建了一个SOCKET以外,还创建了个CSocketWnd窗口对象,并使用WSAAsyncSelect()将这个SOCKET与该窗口对象关联,以让该窗口对象处理来自Socket的事件(消息),然而CSocketWnd收到Socket事件之后,只是简单地回调
CAsyncSocket::OnReceive()
CAsyncSocket::OnSend()
CAsyncSocket::OnAccept()
CAsyncSocket::OnConnect()
等虚函数。所以CAsyncSocket的派生类,只需要在这些虚函数里添加发送和接收的代码。
CSocket是MFC在CAsyncSocket基础上派生的一个同步阻塞Socket的封装类。它是能把CAsyncSocket变成同步的,而且还能响应同样的Socket事件。其实道理很简单,CSocket在Connect()返回WSAEWOULDBLOCK错误时,不是在OnConnect(),OnReceive()这些事件终端函数里去等待。你先必须明白Socket事件是如何到达这些事件函数里的。这些事件处理函数是靠CSocketWnd窗口对象回调的,而窗口对象收到来自Socket的事件,又是靠线程消息队列分发过来的。
总之,Socket事件首先是作为一个消息发给CSocketWnd窗口对象,这个消息肯定需要经过线程消息队列的分发,最终CSocketWnd窗口对象收到这些消息就调用相应的回调函数(OnConnect()等)。
2.5 设计流程分析图
图2 通信流程图
我们只要了解学习套接口的原理和类方法,就可轻松实现程序网络互联通信。
3 程序设计
1) 开始时,创建一个新的MFC AppWizard项目,命名为Sock。第一步明确应用程序是一个基于对话框的程序。第二步,应用程序支持Windows Sockets,如下图3所示,其余选项可以默认。
图3 对话框的选择
2)视窗布局和启动功 创建应用程序外壳后,安排程序的主对话框,需要用到的单选按钮、编辑框、静态文本框等控件的布局如下图。控件属性设置值如下表1。
图4 通信聊天窗口的布局
表1 控件属性设置
对象
属性
设置值
Group box
ID
IDC_STATUCTYPE
Caption
Socket Type
Radio button(2个)
ID
IDC_RCLIENT/IDC_RSERVER
Caption
&Client/&Server
Static text (5个)
ID
IDC_STATICNAME/IDC_ESERVPORT/IDC_STATICMSG/IDC_STATIC/IDC_STATIC
Caption
Server&Name/Server&Port/&Message/Sent/Received
Edit box(4个)
ID
IDC_ESERVNAME/IDC_ESERVPORT/IDC_EMSG
Caption
缺省
Command button(3个)
ID
IDC_ESERVPORT/IDC_BCLOSE/
IDC_BSEND
Caption
C&onnect/C&lose/S&emd
List box(2个)
ID
IDC_LSENT/IDC_LRECVD
Tsn Stop
Unchecked
Sort
Unchecked
Selection
None
主对话框设计完后,打开Class Wizard,把参数送入对话框的控件,参数说明如下表2。
表2 控件参数
对象
名字
分类
类型
IDC_BCONNECT
m_ctlConnet
Control
CButton
IDC_EMSG
m_strMessage
Value
CString
IDC_ESERVNAME
m_strName
Value
CString
IDC_ESERVPORT
m_iPort
Value
int
IDC_LRECVD
m_crlRecvd
Control
CListBox
IDC_LSENT
m_ctlSent
Control
CListBox
IDC_RCLIENT
m_iType
Value
int
通过对控件的属性设计和参数设置,可以对每个控件添加相应的消息函数和响应事件的消息函数。用到的主要函数有如下:
图5 程序中的注意函数列表
注意:各个函数对应的代码见附页,注意添加对应的头文件和类的申明。
4 运行及调试结果
步骤1:打开工作区间,编译程序,没有错误,运行程序可弹出如下对话框!计算机名或IP地址、端口号显示为初始化的数据,可根据需要进行修改。
图6 运行窗口
步骤2:双方通信必有一端做客户机,另一端做服务器,可以根据自己的喜好选择做哪一方。输入计算机名或IP地址及端口号,再在左上角提供的单选按钮进行选择,选择后服务机和客户机分别如下显示,计算机IP地址及端口号被禁用了。服务器先开启监听功能,客户机在开始连接功能!如下图所示。
图7 服务器窗口
图8 客户机窗口
此时客户机和服务器可以进行通信了,如下图,客户机对服务机发送消息:“你好,我是客户机”。发送后的消息将显示到已发消息框里。
图9 客户机运行示例
服务机这边将收到客户机发送的消息,即“你好,我是客户机!”在接收框中。
图10 服务器收到的消息示例
下图为,服务机向客户机发送消息“呵呵,你好,我是服务器”。同样在客户机那里也会收到同样的消息。
图11 客户机运行示例
图12 客户机收到消息示例
图 13 客户机再次运行示例
如果服务机和客户机不想通信了,单击断开按钮,则双方不能通信,退出程序。
5 设计的
总结
初级经济法重点总结下载党员个人总结TXt高中句型全总结.doc高中句型全总结.doc理论力学知识点总结pdf
和体会
此次课程设计的目的是:综合运用本课程及计算机网络的相关知识设计并实现一个网络应用程序,以Visual C++作为开发平台,通过实践复习巩固课堂所学的理论知识,提高对所学知识的综合应用能力。
在该次课程设计的制作我主要是参照了图书馆内的相关书籍,找到一个类似的程序,然后按照书上的内容一步步的做出来了,虽然这个程序算不上是我自己写出来的,但通过这样的一个过程,还是让我学会了很多东西,也算能比较熟练地掌握MFC这一个软件了,这算是一个不小的收获吧,而且,在做这个程序的过程中,让我认识到了在做这样程序中,遇到解决不了的问题与同学的讨论时很重要的,譬如可以以运行,但是就是无法出现连接的显示和状态。最后与同学讨论后,才知道是服务器端有了错误,没有设置自己的IP地址,然后对于客户端进行了一番修改,才终于出现了上述的结果。虽然没有彻底做的出来,但是还是比较开心的,因为自己知道了哪里不足,哪里不可以,可以在以后多多的做练习来充实自己。
在课程设计过程中,收获知识,提高能力的同时,我也学到了很多人生的哲理,懂得怎么样去制定计划,怎么样去实现这个计划,并掌握了在执行过程中怎么样去克服心理上的不良情绪。因此在以后的生活和学习的过程中,我一定会把课程设计的精神带到生活中,不畏艰难,勇往直前!
我以后还是需要多多的练习,多多的勤奋,这样才有可能让自己有信心,有动力,让自己不至于懂的太少而怯场,因为不懂而不会做,相信自己以后会编写出让自己满意的程序和软件的。
附件 相应的函数对应的程序清单
程序清单1 CChatDlg OnRType()
void CChatDlg::OnRType()
{
// TODO: Add your control notification handler code here
UpdateData(TRUE);
if(m_iType==0)
{
m_ctlConnect.SetWindowText("连接");
GetDlgItem(IDC_RSERVER)->EnableWindow(FALSE);
}
else
{
m_ctlConnect.SetWindowText("监听");
GetDlgItem(IDC_RCLIENT)->EnableWindow(FALSE);
}
UpdateData(FALSE);
}
程序清单2 CMyChat SetParent函数
void CMyChat::SetParent(CDialog* pWnd)
{
m_pWnd=pWnd;
}
程序清单3 CChatDlg OnAccept()函数
void CChatDlg::OnAccept()
{
m_sListenSocket.Accept(m_sConnectSocket);
GetDlgItem(IDC_EMSG)->EnableWindow(TRUE);
GetDlgItem(IDC_BSEND)->EnableWindow(TRUE);
GetDlgItem(IDC_STATICMSG)->EnableWindow(TRUE);
GetDlgItem(IDC_BCLOSE)->EnableWindow(TRUE);
}
程序清单4 CChatDlg OnInitDialog()函数
BOOL CChatDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// Add "About..." menu item to system menu.
// IDM_ABOUTBOX must be in the system command range.
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);
}
}
// Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE);
// Set big icon
SetIcon(m_hIcon, FALSE);
// Set small icon
// TODO: Add extra initialization here
//默认是客户机
//
m_iType=0;
//环回IP
m_strName="loopback";
//服务商品号
m_iPort=4000;
//初始时未连接
m_bConnected=FALSE;
//FALSE=对话框初始化数据,TRUE=对话框的获取数据
UpdateData(FALSE);
//设置连接套接字的父窗口也是对话框
m_sConnectSocket.SetParent(this);
//设置监听套接字的父窗口也是对话框
m_sListenSocket.SetParent(this);
return TRUE; // return TRUE unless you set the focus to a control
}
程序清单5 CChatDlg OnConnect()函数
void CChatDlg::OnBconnect()
{
// TODO: Add your control notification handler code here
UpdateData(TRUE);
//锁定上部编辑区
GetDlgItem(IDC_BCONNECT)->EnableWindow(FALSE);
GetDlgItem(IDC_ESERVNAME)->EnableWindow(FALSE);
GetDlgItem(IDC_ESERVPORT)->EnableWindow(FALSE);
GetDlgItem(IDC_STATICNAME)->EnableWindow(FALSE);
GetDlgItem(IDC_STATICPORT)->EnableWindow(FALSE);
GetDlgItem(IDC_RSERVER)->EnableWindow(FALSE);
GetDlgItem(IDC_RCLIENT)->EnableWindow(FALSE);
GetDlgItem(IDC_STATICTYPE)->EnableWindow(FALSE);
GetDlgItem(IDC_BCLOSE)->EnableWindow(TRUE);
if(m_iType==0)
{
m_sConnectSocket.Create();
m_sConnectSocket.Connect(m_strName,m_iPort);
}
else
{
m_sListenSocket.Create(m_iPort);
m_sListenSocket.Listen();
}
}
程序清单6 CChatDlg OnAccept()
void CChatDlg::OnAccept()
{
m_sListenSocket.Accept(m_sConnectSocket);
GetDlgItem(IDC_EMSG)->EnableWindow(TRUE);
GetDlgItem(IDC_BSEND)->EnableWindow(TRUE);
GetDlgItem(IDC_STATICMSG)->EnableWindow(TRUE);
GetDlgItem(IDC_BCLOSE)->EnableWindow(TRUE);
}
程序清单7 CChatDlg OnConnect函数
void CChatDlg::OnConnect()
{
// Enable the text and message controls
GetDlgItem(IDC_EMSG)->EnableWindow(TRUE);
GetDlgItem(IDC_BSEND)->EnableWindow(TRUE);
GetDlgItem(IDC_STATICMSG)->EnableWindow(TRUE);
GetDlgItem(IDC_BCLOSE)->EnableWindow(TRUE);
}
程序清单8 CChatDlg OnBsend函数
void CChatDlg::OnBsend()
{
// TODO: Add your control notification handler code here
int iLen;
int iSent;
UpdateData(TRUE);
if(m_strMessage!=""){
iLen=m_strMessage.GetLength();
iSent = m_sConnectSocket.Send(LPCTSTR(m_strMessage),iLen);
if(iSent==SOCKET_ERROR)
{}
else{
m_ctlSent.AddString(m_strMessage);
m_strMessage="";
UpdateData(FALSE);
}
}
}
程序清单9 CChatDlg OnReceive()
void CChatDlg::OnReceive()
{
char *pBuf = new char[1025];
//留一个NULL
int iBufSize = 1024;
int iRcvd;
CString strRecvd;
// 接收消息
iRcvd = m_sConnectSocket.Receive(pBuf, iBufSize);
// 是否收到了内容
if (iRcvd == SOCKET_ERROR) {
}
else {
//
pBuf[iRcvd] = NULL;
// 赋值
strRecvd = pBuf;
m_ctlRecvd.AddString(strRecvd);
// 赋值变量到控件
UpdateData(FALSE);
}
}
程序清单10 CChatDlg OnClose()
void CChatDlg::OnClose()
{
m_sConnectSocket.Close();
GetDlgItem(IDC_EMSG)->EnableWindow(FALSE);
GetDlgItem(IDC_BSEND)->EnableWindow(FALSE);
GetDlgItem(IDC_STATICMSG)->EnableWindow(FALSE);
GetDlgItem(IDC_BCLOSE)->EnableWindow(FALSE);
if(m_iType==0){
GetDlgItem(IDC_BCONNECT)->EnableWindow(TRUE);
GetDlgItem(IDC_ESERVNAME)->EnableWindow(TRUE);
GetDlgItem(IDC_ESERVPORT)->EnableWindow(TRUE);
GetDlgItem(IDC_STATICNAME)->EnableWindow(TRUE);
GetDlgItem(IDC_STATICPORT)->EnableWindow(TRUE);
//
GetDlgItem(IDC_RSERVER)->EnableWindow(TRUE);
GetDlgItem(IDC_RCLIENT)->EnableWindow(TRUE);
GetDlgItem(IDC_STATICPORT)->EnableWindow(TRUE);
}
else{
GetDlgItem(IDC_BCONNECT)->EnableWindow(TRUE);
GetDlgItem(IDC_ESERVNAME)->EnableWindow(TRUE);
GetDlgItem(IDC_ESERVPORT)->EnableWindow(TRUE);
GetDlgItem(IDC_STATICNAME)->EnableWindow(TRUE);
GetDlgItem(IDC_STATICPORT)->EnableWindow(TRUE);
GetDlgItem(IDC_RSERVER)->EnableWindow(TRUE);
//
GetDlgItem(IDC_RCLIENT)->EnableWindow(TRUE);
GetDlgItem(IDC_STATICPORT)->EnableWindow(TRUE);
}
}
程序清单11 CChatDlg OnBclose
void CChatDlg::OnBclose()
{
// TODO: Add your control notification handler code here
OnClose();
}
发送连接请求
发送连接请求
发送连接请求
客户机
服务器(监控)
1