通信网络程序的设计第10章-面向对象技术课件.ppt
- 【下载声明】
1. 本站全部试题类文档,若标题没写含答案,则无答案;标题注明含答案的文档,主观题也可能无答案。请谨慎下单,一旦售出,不予退换。
2. 本站全部PPT文档均不含视频和音频,PPT中出现的音频或视频标识(或文字)仅表示流程,实际无音频或视频文件。请谨慎下单,一旦售出,不予退换。
3. 本页资料《通信网络程序的设计第10章-面向对象技术课件.ppt》由用户(三亚风情)主动上传,其收益全归该用户。163文库仅提供信息存储空间,仅对该用户上传内容的表现方式做保护处理,对上传内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知163文库(点击联系客服),我们立即给予删除!
4. 请根据预览情况,自愿下载本文。本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
5. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007及以上版本和PDF阅读器,压缩文件请下载最新的WinRAR软件解压。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 通信 网络 程序 设计 10 面向 对象 技术 课件
- 资源描述:
-
1、1 1第10章 面向对象技术10.1 面向对象概述面向对象概述10.2 MFC CAsyncSocket类网络编程类网络编程10.3 MFC CSocket类网络编程类网络编程10.4 多媒体通信编程多媒体通信编程小结小结2 2除了采用链接库的封装方法,还有一种更具有优势的封装方法面向对象类封装。面向对象的编程技术采用与传统面向过程的编程方法不同的思想,已经在单机的应用程序设计中得到了有效验证。同样,在网络编程中,也可以提高程序的复用性和可读性。本章首先从面向对象的封装、继承和多态入手,在此基础上介绍了两种MFC提供的两种套接字类,为了深入介绍面向对象网络编程的好处,将其应用于多媒体通信编程。
2、两种套接字类是对传统API函数的封装,将二者比较进行学习有益于对本章内容的掌握。3 3在传统的面向过程的程序设计中:程序=算法+数据结构,这里的算法实际上就是功能抽象。在面向过程的程序设计中,程序是模块化的,模块是分层次的,层与层之间是一个从上往下的调用关系,如图10-1。10.1 面向对象概述面向对象概述4 4图10-1 面向过程的程序组织5 5图10-2 面向对象的程序组织6 6然而,功能抽象是困难的,而且很难全面。一旦要解决的问题发生一点小变化,功能块就要重编,而一个功能块又被多个上层模块调用,它们的要求有的变了、有的没变,这就给重编带来极大的困难。具体的缺陷表现为:利用传统的面向过程的
3、程序开发,即使开发一个简单的Windows应用程序也需要对编程原理有很深刻的认识,需要手工编写冗长的代码;程序的出错率是随着代码长度的增加呈几何级数增长的,当程序长度逐渐膨胀时,调试程序也会变得越来越困难。7 7鉴于面向过程的程序设计存在的缺陷,20世纪90年代流行起来的面向对象的程序设计将面向过程的程序设计核心思想替换为:程序=对象+对象+对象,其中对象=算法+数据结构。这样,程序变为一个个封装对象的结合体,而对象由紧密结合在一起的算法和数据结构组成,对象中有数据和对数据的操作,具有完整的个体功能,如图10-2所示。类是用来定义对象的一种抽象数据类型,它是产生对象的模板。类可以认为是一种特殊
4、的结构体,基本上说C+对C语言的最重要的改进就是增加了“类”这种数据类型。8 810.1.1 封装封装封装即是将某种东西包装隐藏起来,让外界无法直接使用,只能通过某些特定的方式才能访问。封装是面向对象的基础,它将底层的元素组合起来形成新的高层次实体,实质上是一种信息隐藏技术。面向对象是以类为单位进行代码的封装。在前面面向过程的编程中,我们已经知道函数也是封装的一种形式。函数将所执行的细节行为封装在函数本身这个更大的实体中,被封装的元素隐藏了它们的实现细节(可以调用函数却不能访问它所执行的语句)。与之类似,类也是一个封装的实体,它代表若干成员的聚集,它们中的大多数同样隐藏了实现该类型的成员。9
5、9定义一个类时也就定义了一个类型,用这个类型可以定义一个对象(类的用户),计算机系统会为定义的对象分配存储空间。类由类成员组成,成员又由成员变量和成员函数组成,分别代表类的特性和行为。成员又划分为三种类型,即public、private、protected,这三种类型实现了对类封装的分层次的信息隐藏。public成员:该类型成员可以被使用该类型的所有代码访问。private成员:该类型成员只可被本类其他类成员或友元(friend)访问,子类不可继承和访问。10 10protected成员:该类型成员可被其他类成员或友元访问,也可被子类继承和访问。对象只能访问public成员。这三种成员类型的访
6、问关系,可以用下面的程序进行说明。class Aprivate:int a;public:int b;11 11 void f1()a=0;b=1;c=2;protected:int c;class B:public Apublic:int d;void f2()c=0;12 12根据成员public、private、protected的性质,对A、B对象的访问A ca、ca.b=1、ca.f1()、B cb、cb.b=2、cb.d=3、cb.f1()、cb.f2()均是合法的。对于ca.a、ca.c、cb.a、cb.c的访问都不合法。13 1310.1.2 继承继承通俗地讲,后代具有源自祖先
7、的某些特点就叫继承。如果只有封装,那么非面向对象语言的结构体也能做到,继承则把代码复用提升到了一个新高度。面向对象的继承包含两层含义,即继续和发展。不继续父类的特性则失去继承的本义,子类不发展出新的特性则失去存在意义(沿用父类即可)。继承是一种树状的层次关系,子类在继承祖先类的成员变量和成员函数的同时,也可以定义自己的成员变量和成员函数。14 14子类继承父类有三种方法,即公共、私有和受保护继承(为了区别public、private和protected,这里使用中文),这三种继承方法会使得父类中的成员信息隐藏特性发生变化,具体如下:公有继承:基类的成员保持自己的访问级别,基类的public成员
8、为派生类的public成员,基类的protected成员为派生类的protected成员。私有继承:基类的所有成员在派生类中变为private成员。受保护继承:基类的public和protected成员在派生类中变为protected成员。15 15继承的本质就是实现代码重用,因而继承机制能够缩短软件的开发周期,加快编程速度。16 1610.1.3 多态多态为了增加类的继承灵活性,面向对象技术提出了类的多态(动态绑定)特性,简称多态性。多态性是指发出的同样消息被不同类型的对象接收有可能导致完全不同的行为。利用多态性技术可以用同一个函数名的函数,实现完全不同的功能,这与客观世界的事实完全相符。多
9、态是面向对象系统的重要特性,对于同一个消息可以根据发送消息的对象的不同采用多种不同的处理方式。多态性主要是依靠virtual(虚函数)实现的,C+中在成员函数的最前面加上关键字virtual就可以将该函数设置为虚函数,在子类中可以使用相同的函数名对其进行重新定义。17 17对于在父类中无法被具体定义的虚函数,可以将其定义为纯虚函数(即函数定义后再加上“=0”的说明)。纯虚函数一般不在(通常也无法在)父类中具体定义,仅在子类中具体定义,这种定义很有用,例如:“动物”这个类可以派生出“昆虫”、“哺乳动物”、“鸟”等子类,但是在动物类本身中无法具体定义“吃”这个函数,因此需将eat()定义为纯虚函数
10、,如下:class animal public:virtual void eat()=0;18 18有纯虚函数的类不能直接生成对象,即上述的类的“animal a;”就不合法。需注意的是,虚函数只在public和protected中定义,针对父类中可能在子类中修改的函数才适合。构造函数因其里面要插入对虚函数表指针的初始化语句,因此也不能声明为虚函数。通常,尽可能地把函数声明为虚函数是一个好的编程习惯,这样做增加了子类设计的自由度。在MFC(参见2.8.2节)中,微软利用这个类库践行了面向对象网络编程的优越性,10.2节和10.3节将分别进行介绍。鉴于篇幅原因,关于更多的面向对象的知识请参阅其他
11、书籍,这里仅作概念性介绍。19 19如前所述,MFC封装了大约有100多个类,直接与套接字编程有关的主要是两个类,即CAsyncSocket和CSocket(还有一个从CSocket派生的CCeSocket类,主要用于WinCE平台,这里不记在内),从本节开始将分别进行介绍。10.2 MFC CAsyncSocket类网类网络编程络编程202021 2110.2.1 CAsyncSocket类类CAsyncSocket派生自CObject类(结构如图10-3所示),利用它可以方便地处理有关网络行为的通知消息。CAsyncSocket封装了低层的WinSock API,它在原有的WinSock函
12、数的基础上提供了一些面向对象的特性,如连接、接收事件。与其他面向对象的C+插口类不同,CAsyncSocket类所提供的唯一的抽象就是将与套接字相联系的Windows消息以回调函数的形式表示,可以说CAsyncSocket类是用于异步WinSock调用的一个包容类。2222缺省情况下,使用该类创建的Socket是非阻塞的Socket,所有操作都会立即返回,如果没有得到结果,返回WSAEWOULDBLOCK,表示是一个阻塞操作。CAsyncSocket有一个特殊的成员变量m_hSocket,用来保存其对应的Socket句柄。与前面介绍的基于WinSock API的编程接口相比,CAsyncSoc
13、ket类的编程接口除了封装了低层的WinSock API,还增加了很多智能化的设计,最重要的就是对I/O模型(参见6.6.2节)的封装,从而把程序员从复杂的I/O管理中解放出来。CAsyncSocket类是通过封装了一个CSocketWnd窗口实现这一功能的,封装是在CAsyncSocket的Create()函数中实现的,函数原型如下:2323bool CAsyncSocket:Create(long lEvent)m_hSocket=socket(PF_INET,SOCK_STREAM,0);/创建Socket本身 CSocketWnd*pSockWnd=new CSocketWnd;/创建
14、响应事件的CSocketWnd窗口 pSockWnd-Create();/将Socket事件和窗口用WSAAsyncSelect关联 WSAAsyncSelect(m_hSocket,pSockWnd-m_hWnd,WM_SOCKET_NOTIFY,lEvent);2424可以看出,该函数除了创建了一个SOCKET以外还创建了一个CSocketWnd窗口对象,并使用WSAAsyncSelect()将这个SOCKET与该窗口对象关联,达到让该窗口对象处理来自Socket的事件(消息)的目的。在MFC框架的支持下,一旦CSocketWnd收到Socket事件后,会回调CAsyncSocket的Do
15、CallBack成员函数,进而调用CAsyncSocket的成员函数OnReceive()、OnSend()、OnAccept()、OnConnect()等虚函数,进行I/O处理。所以使用CAsyncSocket进行套接字编程时,只需要在它的派生类里的这些虚函数里添加用户自己的发送和接收代码即可,而无需再进行I/O模型的管理,这大大简化了编程过程。CAsyncSocket:DoCallBack的原型如下:2525static void PASCAL CAsyncSocket:DoCallBack(WPARAM wParam,LPARAM lParam)CAsyncSocket*pSocket;
16、pSocket.Attach(SOCKET)wParam);/wParam就是触发这个事件的Socket的句柄 int nErrorCode=WSAGETSELECTERROR(lParam);/lParam是错误码与事件码的合成 switch(WSAGETSELECTEVENT(lParam)2626 case FD_READ:pSocket-OnReceive(nErrorCode);break;case FD_WRITE:pSocket-OnSend(nErrorCode);break;case FD_OOB:pSocket-OnOutOfBandData(nErrorCode);bre
17、ak;case FD_ACCEPT:2727 pSocket-OnAccept(nErrorCode);break;case FD_CONNECT:pSocket-OnConnect(nErrorCode);break;case FD_CLOSE:pSocket-OnClose(nErrorCode);break;2828那么CSocketWnd与CAsyncSocket是如何建立联系的呢?是通过CSocketWnd类中定义的消息与函数的映射实现的。该消息映射为BEGIN_MESSAGE_MAP(CSocketWnd,CWnd)ON_MESSAGE(WM_SOCKET_NOTIFY,OnSoc
18、ketNotify)END_MESSAGE_MAP()也就是一旦发生WM_SOCKET_NOTIFY事件(Socket事件),就会调用CSocketWnd:2929OnSocketNotify函数。CSocketWnd:OnSocketNotify函数原型如下:LRESULT CSocketWnd:OnSocketNotify(WPARAM wParam,LPARAM lParam)CAsyncSocket:DoCallBack(wParam,lParam);/收到Socket事件消息后,回调CAsyncSocket的DoCallBack()函数 return 0;实际上就是调用了CAsync
19、Socket:DoCallBack()函数。303010.2.2 类成员类成员下面对CAsyncSocket的类成员函数进行简要介绍,具体定义与使用方法可参看MSDN。1构造函数构造函数CAsyncSocket用来在创建CAsyncSocket对象时初始化对象,为对象成员变量赋初始值,与new运算符一起使用在创建对象的语句中。CAsyncSocke有两个构造函数CasyncSocket()和Create(),前者用于构造一个CAsyncSocket对象,后者用于创建一个socket。31 312属性函数属性函数为了增加程序设计的灵活性和可控性,CAsyncSocket还提供了属性函数和重载函数
20、,大大增加了程序员在编写网络程序时的自由度。CAsyncSocket类的属性函数包括Attach()、Detach()、FromHandle()、GetLastError()、GetPeerName()、GetSockName()、GetSockOpt()和SetSockOpt()函数,它们可以获得或改变对象的属性,为基于CAsyncSocket类的网络编程提供了网络控制与监测工具。32323操作函数操作函数CAsyncSocket操作函数进行网络相关建立的具体操作,与前面介绍的WinSock API的对应函数非常象,实际上就是对这些API函数的封装。操作函数包括Accept()、Bind()
21、、Close()、Connect()、IOCtl()、Listen()、Receive()、ReceiveFrom()、Send()、SendTo()、ShutDown()。33334重载函数重载函数CAsyncSocket类的重载函数能够向相应程序通告套接字事件的发生,可以通过重载设计处理相应的网络通信事件,这些函数都是虚函数。重载函数包括OnAccept()、OnClose()、OnConnect()、OnOutOfBandData()、OnReceive()、OnSend()。后续的网络处理主要就是使用这些函数。CAsyncSocket类本身只有一个成员变量,即m_hSocket,用于指
22、示连接到CAsyncSocket对象的句柄。从前面的叙述可以看出,CAsyncSocket直接封装了低层的WinSock API,同时提供了丰富的成员,简化和丰富了WinSock编程。343410.2.3 编程步骤编程步骤直接使用CAsyncSocket进行网络编程的具体使用方法可以概括为以下五个步骤:(1)在堆或者栈中构造一个CAsyncSocket对象,例如:CAsyncSocket sock或者CAsyncSocket*pSock=new CAsyncSocket;(2)调用Create()创建socket,如:使用缺省参数创建一个面向连接的socket,sock.Create()指定参
23、数创建一个使用数据报的socket,本地端口为30,程序代码如下:pSocket.Create(30,SOCK_DGRM);3535(3)如果是客户程序,使用Connect()连接到远地;如果是服务程序,使用Listen()监听远地的连接请求。当收到连接请求后,调用Accept()接受该请求。在接收连接请求后,就可以执行例如确认之类的操作。(4)使用成员函数进行网络I/O,完成与其他程序的通信和操作。(5)销毁CAsyncSocket,析构函数调用,Close()成员函数关闭socket。在MFC网络编程中,通常不直接使用CAsyncSocket类而是会对CAsyncSocket派生出一个新类
24、,并在该类中增加用户自己的一些网络功能(成员)。3636CSocket类是MFC提供的另外一个套接字类,在CAsyncSocket基础上又增加了一些新特性。10.3 MFC CSocket类网络编程类网络编程373710.3.1 CSocket类类CSocket类建立在CAsyncSocket类的基础上,是CAsyncSocket类的派生类,派生结构如图10-3所示。CSocket类的对象的用法与CAsyncSocket类的对象非常类似,且提供了以下三点改进。1成员成员CSocket主要增加或重载了构造函数Csocket()、Create();属性函数IsBlocking()、FromHand
25、le()、Attach();操作函数CancelBlockingCall();重载函数OnMessagePending()。38382同步化同步化CSocket对CAsyncSocket进行了同步化改造,成为一个典型的同步阻塞Socket封装类。同步的方法很简单,以CSocket的操作函数Connect()为例进行说明。CSocket在Connect()被阻塞时,不是在OnConnect()、OnReceive()这些事件终端函数里去等待,而是马上进入一个消息循环,从当前线程的消息队列里取关心的消息。如果取到了WM_PAINT消息,则刷新窗口;如果取到的是Socket发来的消息,则根据Sock
展开阅读全文