基于MFC的简易聊天室Word文件下载.docx
《基于MFC的简易聊天室Word文件下载.docx》由会员分享,可在线阅读,更多相关《基于MFC的简易聊天室Word文件下载.docx(21页珍藏版)》请在冰点文库上搜索。
2.5利用CSOCKET进行有连接的通信 6
3详细设计 6
3.1客户端的实现 6
3.2服务端的实现 11
4程序运行结果 16
4.1服务器端 16
4.2客户端 16
5结束语 17
6致谢 17
参考文献 17
王伟
(安阳师范学院计算机与信息工程学院,河南 安阳 455002)
摘 要:
网络聊天室,其实质就是基于Internet的一种网络聊天软件。
它可以在网络环境下进行实时的一对多或多对多的匿名交谈。
网络聊天室软件的制作方法有很多种,比如用MFC和Java等语言设计的就有很多,本毕业设计主要是利用MFC所提供的各种控件尤其是
WinSock控件,基于C/S模式,设计了一个网络聊天室,圆满地实现在网络上实时聊天的功能。
关键词:
WinSock;
C/S;
VisualC++6.0;
聊天
1需求分析
当前是数字信息时代,网络时代,任何一种编辑工具都不能忽视在网络上的应用,并且随着Internet的普及和宽带技术的成熟,越来越多的用户进入网络世界中享用浏览新闻、查询信息、发送邮件、在线观看电影等服务,享受网络带来的便利和办公的高效,与此同时一个新型的Web应用程序为网民之间提供了一个实时通信的功能和场所,这就是聊天室。
在网络早期就开始盛行,不论是BBS,IRC都有类似网上聊天室的机制。
聊天室为网友提供了实时性对话的渠道,是网络上极为流行的一项服务。
聊天室适用于网上会议或闲聊的一些场合。
聊天室为网友提供了较好的交友环境,网友之间相互以文字交谈,在形式上有点类似笔友的性质,却大大节省了书信往返的时间,这也是网上交友之所以如此热门的原因。
1.1聊天室程序的开发背景
近年来,互连网发展日新月异,网络使空间的距离不再成为人们沟通的障碍,世界各个角落的人们可以通过Internet收发邮件、实时聊天、获取最新的资讯。
因此本次毕业设计以“面向连接的Winsock网络会话程序开发”为题,制作一个C/S聊天室程序,通过制作该程序还能更好的学习网络socket编程的相关知识。
1.2聊天室的设计目标
本课题是建立聊天通信模型,设计一个聊天室软件,包括服务器端和客户端,主要功能为:
服务器端功能:
(1)初始化socket,创建服务器端。
(2)维护一个链表,保存所有用户的IP地址、端口信息。
(3)接受用户传送来的聊天信息,然后向链表中的所用用户转发。
(4)接受用户传送来的连接判断命令,并向用户发出响应命令。
客户端功能:
客户端界面上的两个文本框,一个用于显示接受的聊天信息,一个用来接受用户输入的聊天信息。
当按下“发送”按钮时将信息发送给服务器。
通过本课题的毕业设计,可以比较深入的了解和掌握WINSOCK控件基本属性、方法和事件,理解网络聊天通信的概念,输控制协议(TCP)进行数据交流,初步掌握网络聊
第18页
成功
天通信程序的设计方法。
并能巩固和扩展大学期间的学习内容,进行项目的设计开发训练,更好的适应社会的需求。
1.3聊天室的实现思想
聊天室程序一般都是以服务器提供服务端连接响应,使用者通过客户端程序连接到服务器。
就可以与同一服务器上的用户交谈,这是一个面向连接的通信过程。
因此,程序要在TCP/IP环境下,实现服务器端和客户端两部分程序。
1.4聊天室的工作流程
(1)服务器端工作流程:
服务器端通过socket()系统调用创建一个Socket数组后
(即设定了接受客户的最大数目),与指定的本地端口绑定bind(),就可以在端口进行监听listen()。
如果有客户端连接请求,则在数组中选择一个空Socket,将可与端地址付给这个Socket。
然后登客户端的用户就可以在服务器上聊天了。
如图1:
初始化
绑定端口
发送或接受
连接请求
失败
接受请求
监听
图1服务器端流程图
(2)客户端工作流程。
客户端程序相对简单,只需要建立一个Socket与服务器连接,成功后通过这个Socket来发送和接收数据就可以了。
如图2:
开始聊天
发送请求
绑定端口和服务器IP
图2客户端流程
2相关知识
2.1Winsock介绍
WindowsSockets规范以U.C.Berkeley大学BSDUNIX中流行的Socket接口为范例定义了一套MicosoftWindows下网络编程接口。
它不仅包含了人们所熟悉的Berkeley
Socket风格的库函数;
也包含了一组针对Windows的扩展库函数,以使程序员能充分地利用Windows消息驱动机制进行编程。
WindowsSockets规范本意在于提供给应用程序开发者一套简单的API,并让各家网络软件供应商共同遵守。
此外,在一个特定版本Windows的基础上,WindowsSockets也定义了一个二进制接口(ABI),以此来保证应用WindowsSocketsAPI的应用程序能够在任何网络软件供应商的符合WindowsSockets协议的实现上工作。
因此这份规范定义了应用程序开发者能够使用,并且网络软件供应商能够实现的一套库函数调用和相关语义。
遵守这套WindowsSockets规范的网络软件,我们称之为WindowsSockets兼容的,而WindowsSockets兼容实现的提供者,我们称之为WindowsSockets提供者。
一个网络软件供应商必须百分之百地实现WindowsSockets规范才能做到现WindowsSockets兼容。
任何能够与WindowsSockets兼容实现协同工作的应用程序就被认为是具有Windows
Sockets接口。
我们称这种应用程序为WindowsSockets应用程序。
WindowsSockets规范定义并记录了如何使用API与Internet协议族(IPS,通常我们指的是TCP/IP)连接,尤其要指出的是所有的WindowsSockets实现都支持流套接口和数据报套接口。
应用程序调用WindowsSockets的API实现相互之间的通讯。
WindowsSockets又利用下层的网络通讯协议功能和操作系统调用实现实际的通讯工作。
虽然我们并不反对使用这一套API来实现另一通讯协议栈(而且我们期望在将来规范的修改中能够讨论这个问题),但这种用法已经超出了我们这一份规范所规定的范围,我们在此将不作讨论。
2.2MFC简介
MFC(MicrosoftFoundationClasses),是一个微软公司提供的类库(classlibraries),以
C++类的形式封装了Windows的API,并且包含一个应用程序框架,以减少应用程序开发人员的工作量。
其中包含的类包含大量Windows句柄封装类和很多Windows的内建控
件和组件的封装类。
MFC是WinAPI与C++的结合,API,即微软提供的Windows下应用程序的编程语言接口,是一种软件编程的规范,但不是一种程序开发语言本身,可以允许用户使用各种各样的第三方(如我是一方,微软是一方,Borland就是第三方)的编程语言来进行对Windows下应用程序的开发,使这些被开发出来的应用程序能在
Windows下运行.这种结合一方面让用户使用微软的专业C++SDK来进行Windows下应用程序的开发变得容易,因为MFC是对API的封装,微软做了大量的工作,隐藏了好多程序开发人员在Windows下用C++&
MFC编制软件时的大量内节,如应用程序实现消息的处理,设备环境绘图,这种结合是以方便为目的的,必定要付出一定代价(这是微软的一向作风),因此就造成了MFC对类封装中的一定程度的的冗余和迂回,但这是可以接受的。
2.3Cdialog类
CDialog类是在屏幕上显示的对话框基类。
对话框有两类:
模态对话框和非模态对话框。
模态对话框在应用继续进行之前必须关闭。
非模态对话框允许用户执行另外的操作而不必取消或删除该对话框。
一个CDialog对象是对话框模板与一个CDialog派生类的组合。
使用对话框编辑器创建对话框并存入资源之中,然后使用 ClassWizard创建一个CDialog派生类。
同其它窗口一样,对话框从Windows中获取信息。
在对话框中你会对来自对话框控件的处理消息感兴趣,因为它说明了对话框是如何与用户交互的。
ClassWizard观察对话框每个控件可能产生的消息,可以选择你所希望处理的消息。
ClassWizard将适当的消息映射器入口和消息处理成员函数加到一个新类中。
你只需为成员函数编写应用的代码。
如果喜欢,在使用ClassWizard时可以编写自己的消息映射器入口和成员函数。
对于大多数普通对话框,可以向对话框派生类中添加成员变量以存储数据。
数据
是用户向对话框中输入的,或者为用户显示数据。
ClassWizard观察对话框中与数据映射的控件并提示为每一控件创建一个成员变量。
同时,为每一变量选择变量类型和取值范围。
ClassWizard将成员变量加入对话框派生类中[3]。
然后,ClassWizard写入成员函数与对话框控件之间的交换数据自动映射的数据。
数据映射使函数可以为对话框控件提供适当的初始值。
检索数据并对数据进行有效性检测。
要建立模态对话框,先使用构造程序为对话框派生类构造一个对象。
然后调用
DoModal创建对话框窗口及其控件。
如果要建立非模态对话框,在构造程序中为对话框类调用Create即可。
还可使用DLGTEMPLATE数据结构在内存中建立模板,该结构在联机文档“Win32 SDK”中有描述。
当构造了一个CDialog对象之后,调用CreateIndirect创建非模态对话框,或调用InitModalIndirect和DoModal来创建模态对话框。
ClassWizard在覆盖它为新对话框类加入的CWnd:
:
DoDataExchange之后写入交换和有效性规则的数据映射。
请参阅CWnd中的DoDataExchange成员函数。
程序和框架都通过调用CWnd:
UpdateData间接调用DoDataExchange。
当用户单击OK按钮关闭模态对话框时,框架调用UpdateData(如果单击了Cancel按钮,将不能获得数据)。
OnInitDialog的缺省方式也是设置控件的初始值。
为得到初始控件,通常要覆盖OnInitDialog。
在所有对话框控件建立且在对话框显示之前,调用
OnInitDialog。
在模态对话框与非模态对话框执行的任意时刻都可以调 CWnd:
UpdateData。
如果要手工创建对话框,应为对话框派生类添加必需的成员变量,并添加已获得
C++程序员指南”中的
数据值的成员函数。
关于ClassWizard的更多信息,请参阅联机文档“Visual
“使用ClassWizard”。
当用户按下OK或Cancel按钮,或者调用EndDialog时,模态对话框自动关闭。
2.4CAsyncsocket类和CSocket类
Cssyncsocket类一个异步非阻塞Socket类封装类,CasyncSocket:
Create()有一个参数指明了你想要处理那些Socket事件,你关心的事件被指定以后,这个Socket默认就被用做了异步方式.的函数,除了一个以外,在创建了一个CSocketWnd窗口对象,使
WSAAsyncSlecet()将这个SOCKET与该窗口对象关联,以让该窗口对象处理来自Socket的事件(消息),然而CSocketWnd收到Socket事件之,只是简单地回
CasyncSocket:
OnReceive()等虚函数。
所以CAsyncSocket的派生类,只需要在这些虚函数里添加发送和接收的代码。
CSocket是MFCCAsyncSocket基础上派生的一个同步阻塞
Socket的封装类。
构造一个CAsyncSocket对象并使用该对象创建基础SOCKET句柄[2]。
套接字的创建遵循两阶段构造的MFC模式。
例如:
CAsyncSocketsock;
sock.Create();
//UsethedefaultparametersCAsyncSocket*pSocket=newCAsyncSocket;
intnPort=27;
pSocket->
Create(nPort,SOCK_DGRAM);
上面的第一个构造函数在堆栈上创建一个CAsyncSocket对象,第二个构造函数在堆上创建CAsyncSocket。
上面的第一个Create调用使用默认参数创建流式套接字,第二个Create调用创建具有指定端口和地址的数据文报套接字。
任一个Create版本都可以和任一种构造方法一起使用。
Create的参数有:
○1“端口”:
短整型。
对于服务器套接字,必须指定端口。
对于客户端套接字,通常接受此参数的默认值,该值允许WindowsSockets选择端口。
○2套接字类型:
SOCK_STREAM(默认值)或SOCK_DGRAM。
套接字“地址”,如“”或“192.168.1.11”。
该地址为网络上的网际协议(IP)地址。
很可能要始终依赖此参数的默认值。
如果套接字是客户端,则使用CAsyncSocket:
Connect将此套接字对象连接到服务器套接字。
如果套接字是服务器,则将套接字设置为开始侦听(使用CAsyncSocket:
Listen)来自客户端的连接尝试。
接收到连接请求时,用CAsyncSocket:
Accept接受该请求。
接受连接后,可以执行验证密码等任务。
注意 Accept 成员函数采用对新的空 CSocket 对象的引用作为它的参数。
在调用
Accept之前,必须构造该对象。
如果此套接字对象超出范围,则连接关闭。
不要对这个新套接字对象调用Create。
有关示例,请参见文章WindowsSockets:
操作顺序。
通过调用CAsyncSocket对象的封装WindowsSocketsAPI函数的成员函数,与其他套接字进行通信。
如果在堆栈上创建了套接字对象,当包含函数超出范围时将调用此对象的析构函数。
如果使用new运算符在堆上创建了套接字对象,则您必须负责使用delete运算符销毁此对象。
析构函数在销毁对象之前调用对象的Close成员函数。
有关代码中该顺序的示例(实际上是对于 CSocket 对象),请参见 Windows
Sockets:
操作顺序[1],您对CAsyncSocket的责任。
创建CAsyncSocket类的对象后,该对象封装WindowsSOCKET句柄并提供对此句柄的操作。
使用CAsyncSocket时,如果您直接使用API,则必须处理可能面对的所有问题。
例如:
“阻塞”方案;
发送和接收计算机之间的字节顺序差异;
在Unicode和多字节字符集(MBCS)字符串之间转换。
2.3利用CSocket进行有连接的通信
微软的MFC把复杂的WinSockAPI函数封装到类里,这使得编写网络应用程序更容易。
CAsyncSocket类逐个封装了WinSockAPI,为高级网络程序员提供了更加有力而灵活的方法。
这个类基于程序员了解网络通讯的假设,目的是为了在MFC中使用WinSock,程序员有责任处理诸如阻塞、字节顺序和在Unicode与MBCS间转换字符的任务。
为了给程序员提供更方便的接口以自动处理这些任务,MFC给出了CSocket类,这个类是由
CAsyncSocket类继承下来的,它提供了比CAsyncSocket更高层的WinSock API接口。
Csocket类和CsocketFile类可以与Carchive类一起合作来管理发送和接收的数据,这使管理数据收发更加便利。
CSocket对象提供阻塞模式,这对于Carchive的同步操作是至关重要的。
阻塞函数(如Receive()、Send()、ReceiveFrom()、SendTo()和Accept())直到操作完成后才返回控制权,因此如果需要低层控制和高效率,就使用CasyncSock类;
如果需要方便,则可使用Csocket类。
使用CSocket对象涉及CArchive和CSocketFile类对象。
以下介绍的针对字节流型套接字的操作步骤中,只有第3步对于客户方和服务方操作是不同的,其他步骤都相同。
(1)造一个CSocket对象。
(2)使用这个对象的Create()成员函数产生一个socket对象。
在客户方程序中,除非需要数据报套接字,Create()函数一般情况下应该使用默认参数。
而对于服务方程序,必须在调用Create时指定一个端口。
需要注意的是,Carchive类对象不能与数据报
(UDP)套接字一起工作,因此对于数据报套接字,CAsyncSocket和CSocket 的使用方法是一样的。
(3)如果是客户方套接字,则调用CAsyncSocket ∷Connect()函数与服务方套接字连接;
如果是服务方套接字,则调用CAsyncSocket∷Listen()开始监听来自客户方的连接请求,收到连接请求后,调用CAsyncSocket∷Accept()函数接受请求,建立连接。
请注意Accept()成员函数需要一个新的并且为空的CSocket对象作为它的参数,解释同上。
(4)产生一个CSocketFile对象,并把它与CSocket对象关联起来。
(5)为接收和发送数据各产生一个CArchive 对象,把它们与CSocketFile对象关联起来。
切记CArchive是不能和数据报套接字一起工作的。
(6)使用CArchive对象的Read()和Write()等函数在客户与服务方传送数据。
(7)通讯完毕后,销毁CArchive、CSocketFile和CSocket对象。
3详细设计
我们利用WinSocket实现一个网络聊天室。
需要一个聊天服务器,它可以和很多客户端进行通信,从而把来自不同的客户的聊天信息转交到所有其他的客户端。
这样就形成了一个采用Client/Server结构的并可以多人同时在线的聊天室。
3.1客户端的实现
(1)首先启动VisualC++6.0,利用MFCAppWizard[EXE]建立一个新的MFC工程,工程名为tcpclient,在MFCAppWizardStep1的时候选择Dialogbased即基于对话框,在
Step4时勾选WindowsSockets选项(如图3),其他默认值下一步。
图3MFC的设置
(2)客户端主要分为三个窗口,第一个是连接窗口,需要输入连接到服务器的相关设置信息;
第二个是聊天信息显示窗口,该窗口显示登录服务器以来发送和接收到的消息;
第三个是消息编辑发送窗口,需要输入你要发送的信息内容并发送。
新建一个对话框,并添加各种控件(见控件表1)如图4:
图4 聊天窗口布局
表1
控件类型及各自ID
标题
控件类型
控件ID
连接
Static
IDC_STATIC
信息区
我的ID:
服务器ID:
端口号(默认520)连接服务器
StaticStaticStatic
Button
IDC_STATICIDC_STATICIDC_STATIC
IDC_connet
发送(回车)
IDC_send
编辑框1
编辑框2
编辑框3
编辑框4
编辑框5
EditEditEditEdit
Edit
IDC_EDIT1IDC_EDIT2IDC_EDIT3IDC_EDIT4
IDC_EDIT5
其中编辑框1:
服务器IP;
编辑框2:
端口号;
编辑框3:
消息显示区;
编辑框4:
消息编辑区;
编辑框5:
我的ID。
(3)服务器IP编辑框控件IDC_EDIT1对应的成员变量为OnChangeEdit1。
端口号编辑框控件IDC_EDIT2对应的成员变量为OnChangeEdit2。
消息显示区编辑框控件IDC_EDIT3对应的成员变量为OnChangeEdit3。
消息编辑区编辑框控件IDC_EDIT4对应的成员变量为OnChangeEdit4。
我的ID编辑框控件IDC_EDIT5对应的成员变量为OnChangeEdit5。
(4)下面重点介绍一下单击连接服务器按钮时的处理网络连接的函数。
代码设置如下:
voidCTcpclientDlg:
Onconnet()
{
//TODO:
Addyourcontrolnotificationhandlercodehereif(clconect)clconect.Close();
CStringipstr,portstr;
int