近年来,利用Internet进行网际间通讯,在WWW浏 览、FTP、Gopher这些常规服务,以及在
网络电话、多媒体会议等这些对实时性要求严格 的应用中成为研究的热点,而且已经是必需的了。
Windows环境下进行通讯程序设计的最基本方法是应用
Windows Sockets实现进程间的通讯,为此微软提供了大量基于
Windows Sockets的通讯API,如WinSockAPI、WinInetAPI和ISAPI,并一直致力于开发更快、 更容易的通讯API,将其和MFC集成在一起以使通讯编程越来越容易。本实例重点介绍使用MFC的CSocket类编写
网络通讯程序的方法,并通过使用CSocket类实现了
网络聊天程序。程序编译运行后的界面效果如图一所示:
![利用MFC的Csocket类实现<a]() 网络通信(图) hspace=0 src="/article/UploadPic/2006-5/200651213539384.jpg" border=1 onload="return imgzoom(this,550);" onclick="javascript:window.open(this.src);" style="cursor: pointer;"/> 图一、 网络聊天程序界面效果图 |
一、实现方法 微软的MFC把复杂的WinSock API函数封装到类里,这使得编写
网络应用程序更容易。CAsyncSocket类逐个封装了WinSock API,为高级
网络程序员 提供了更加有力而灵活的方法。这个类基于程序员了解
网络通讯的假设,目的是为了在MFC中使用WinSock,程序员有责任处理诸如阻塞、字节顺序和在Unicode与MBCS 间转换字符的任务。为了给程序员提供更方便的接口以自动处理这些任务,MFC给出 了CSocket类,这个类是由CAsyncSocket类继承下来的,它提供了比CAsyncSocket更高层的WinSock API接口。Csocket类和CsocketFile类可以与Carchive类一起合作来管理发送和接收的数据,这使管理数据收发更加便利。CSocket对象提供阻塞模式,这对于Carchive的同步操作是至关重要的。阻塞函数(如Receive()、Send()、ReceiveFrom()、SendTo() 和Accept())直到操作完成后才返回控制权,因此如果需要低层控制和高效率,就使用CasyncSock类;如果需要方便,则可使用Csocket类。
一些
网络应用程序(如
网络电话、多媒体会议工具)对实时性要求非常强,要求能够直接应用WinSock发送和接收数据。为了充分利用MFC 的优势,首选方案应当是MFC中的CAsyncSocket类或CSocket类,这两个类完全封装了WinSock API,并提供更多的便利。本实例介绍应用这两个类的编程模型,并引出相关的成员函数与一些概念的解释。
CSocket类是由CAsyncSocket继承而来的,事实上,在MFC中CAsyncSocket 逐个封装了WinSock API,每个CAsyncSocket对象代表一个
Windows Socket对象,使用CAsyncSocket 类要求程序员对
网络编程较为熟悉。相比起来,CSocket类是CAsyncSocket的派生类, 继承了它封装的WinSock API。
一个CSocket对象代表了一个比CAsyncSocket对象更高层次的
Windows Socket的抽象,CSocket类与CSocketFile类和CArchive类一起工作来发送和接收数据,因此使用它更加容易使用。CSocket对象提供阻塞模式,因为阻塞功 能对于CArchive的同步操作是至关重要的。在这里有必要对阻塞的概念作一解释: 一个socket可以处于"阻塞模式"或"非阻塞模式",当一个套接字处于阻塞模式(即同步操作)时,它的阻塞函数直到操作完成才会返回控制权,之所以称为阻塞是因为此套接字的阻塞函数在完成操作返回之前什么也不能做。如果一个socket处于非阻塞模式(即异步操作),则会被调用函数立即返回。在CAsyncSocket类中可以用GetLastError 成员函数查询最后的错误,如果错误是WSAEWOULDBLOCK则说明有阻塞,而CSocket绝不会返回WSAEWOULDBLOCK,因为它自己管理阻塞。微软建议尽量使用非阻塞模式,通过
网络事件的发生而通知应用程序进行相应的处理。但在CSocket类中,为了利用CArchive 处理通讯中的许多问题和简化编程,它的一些成员函数总是具有阻塞性质的,这是因为CArchive类需要同步的操作。
在Win32环境下,如果要使用具有阻塞性质的套接字,应该放在独立的工作线程中处理,利用多线程的方法使阻塞不至于干扰其他线程,也不会把CPU时间浪费在阻塞上。多线程的方法既可以使程序员享受CSocket带 来的简化编程的便利,也不会影响用户界面对用户的反应。
CAsyncSocket类编程模型
在一个MFC应用程序中,要想轻松处理多个网 络协议,而又不牺牲灵活性时,可以考虑使用CAsyncSocket类,它的效率比CSocket 类要高。CAsyncSocket类针对字节流型套接字的编程模型简述如下:
1、构造一个CAsyncSocket对象,并用这个 对象的Create成员函数产生一个Socket句柄。可以按如下两种方法构造:
CAsyncSocket sock; //使用默认参数产生一个字节流套接字 Sock.Create(); |
或在指定端口号产生一个数据报套接字
CAsyncSocket*pSocket=newCAsyncSocket; intnPort=27; pSocket->Create(nPort,SOCK-DGRAM); |
第一种方法在栈上产生一个CAsyncSocket对象, 而第二种方法在堆上产生CAsyncSocket对象;第一种方法中Create()成员函数用缺省参数产生一个字节流套接字,第二种方法中用Create()成员函数在指定的端口产生一个数字报套接字。Create()函数的原型为: