用多线程枝术实现Winsock编程.pdf
《用多线程枝术实现Winsock编程.pdf》由会员分享,可在线阅读,更多相关《用多线程枝术实现Winsock编程.pdf(6页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、用多线程枝术实现W insock编程王广伟李维钊摘要本文在对W indow s网络(W inSock)编程作一般性介绍的基础上,对在V isual C+6.0环境下的如何进行网络编程以及如何使用多线程进行网络编程作了介绍和示范。通过本文,读者可以掌握简单的网络编程,并学会使用多线程来进行网络编程。关键词网络套接字阻塞多线程一、W indsock简介W insock(W indow s Sockets)是微软的窗口系统结构(WOSA)的一部分。它是基于UN IX上的BerKeley SoftwareD istribution(BSD)版本的套接字,并为w indow s进行了专门的扩展。Inte
2、rnet是在UN IX系统上发展起来的,在UN IX上有许多成熟的编程接口,其中最通用的是一种叫做Sockets(套接字)的接口。套接字的实质是通信端点的一种抽象,它提供一种发送和接收数据的机制。在1991年前后,许多网络软件商都在加紧研制W indow s下的TCP?IP通迅组件,为了能使这些组件有一定的标准,降低开发难度,他们决定为W indow s开发一套标准的、通用的TCP?IP编程接口,并使之类似于UN IX下的Sockets,这一接口迅速被所有的软件商所接受,包括M icrosoft与I BM。到1994年,它被正式制定成一项标准,称为W indow s Sockets或称W I
3、N SOCK,并通过C语言的动态连接库方式提供给用户及软件开发者。我们现在看到的W indow s下的Internet软件都是在W I N SOCK基础下开发的。随着W indow s 95推出,W I N SOCK已经被正式集成到了W indow s系统中,同时包括了16位与32位的编程接口。W I N SOCK的实现一般都由两部分组成:开发组件和运行组件。开发组件是供程序员开发W I N SOCK应用程序使用的,它包括介绍W I N SOCK实现的文档、W I N SOCK应用程序接口(A P I)引入库和一些头文件。运行组件是W I N SOCK应用程序接口的动态连接库(DLL),文件名
4、为W I N SOCK.DLL应用程序在执行时通过装入它来实现网络通信功能。最初,W I N SOCK1.1版是专门为Internet设计的,现在的2.x版已经不再限于Internet和TCP?IP协议,它通过提供扩展的SP I编程接口,把自己的应用范围扩大到现存的和正在出现的各种网络和协议,包括PSTN、ISDN、无线网、所有的局域网协议、异步传输模式A TM等等,并且允许应用程序对所建立连接的可靠性、冗余度和带宽进行控制。所以掌握了W I N SOCK编程,就等于掌握了W indow s环境下网络编程的一把钥匙。W indow s开网络编程的规范W indow s Sockets。这套规范
5、是w indow s下得到广泛应用的、开放的、支持多种协议的网络编程接口。W indow s Sockets规范定义并记录了如何使用A P I与Internet协议族(IPS,通常我们指的是TCP?IP)连接,尤其要指出的是所有的W indow s Sockets实现都支持流套接口和数据报套接口。应用程序调用W indow s Sockets的A P I实现相互之间的通讯。W indow s Sockets又利用下层的网络通讯协议功能和操作系统调用实现实际的通讯工作。它们之间的关系如图1。二、套接字的两种形式套接字是通信端点的一种抽象,它提供一种发送和接收数据的机制,在W indow s套接字
6、中1。它有两种形式:数据报套接字(Datagram Socket)和流式套接字(Stream Socket).流式套接口采用的是传输控制协议TCP,它提供了双向的,有序的,无重复并且无记录过界的数据流服务,在这种方式下,两个通讯的应用程序之间先要建立一种虚拟的连接,流方式的特点的是:通讯可靠,对数据有校验和重发的机制,通常用来作数据文件的传输如ftp、telnet等,适合于大量数据的传输。数据报套接口采用的是用户数据报协议UDP,它建立在53M icrocomputer Applications Vol.16,No.5,2000开发应用微型电脑应用2000年第16卷第5期李维钊山东大学电子工程
7、系济南250100王广伟山东大学电子工程系硕士研究生济南250100IP协议上,提供无连接数据报传输,支持双向的数据流,但并不保证是可靠,有序,无重复和。也就是说,一个从数据报套接口接收信息的进程有可能发现信息重复了,或者和发出时的顺序不同。数据报套接口的一个重要特点是它保留的记录边界,对于这一特点,数据报套接口采用了与现在许多包交换网络(例如以太网)非常类似的模型,数据报文方式由于取消了重发校验机制,能够达到较高的通讯速率,可以用作一些对数据可靠性要求不高的通讯,如实时的语音、图像转送、广播消息等。是使用流式套接字还是使用数据报套接字,以通信效率影响较大。在编程中,流式套接字与数据报套接字是
8、有区别的。在流式套接字中,服务器首先启动,通过调用socket()建立一个套接口。然后调用bind()将该套接口和本地网络地址联系在一起,再调用listen()使套接口做好侦听的准备,并规定它的请求队列的长度,之后就调用accept()来接收连接,客户在建立套接口后就可调用connect()和服务器建立连接,连接一旦建立,客户机和服务器之间就可以通过调用read()和w rite()来发送和接收数据。最后,待数据传送结束后,双方调用close()关闭套接口。如图3所示。与流式套接字不同的是,在数据报套接字中,服务器不调用accept(),客户机不调用connect()。在发送数据之前,客户机和
9、服务器之间尚未建立完整相关,无连接服务器通过sock2et()和bind()建立了本地半相关。在传输数据之前,无连接的两个端点已建立起来,分别以一个本地Socket号和信宿端Socket地址。于是,一个完整的相关在数据收发过程中动态地建立起来,实现无连接客户和服务器彼此识别。如图2所示。三、通信的选择方式在进行网络开发时,必须对是使用阻塞方式(blockingmode)还是非阻塞方式(non-blocking mode)进行选择。在网络通讯中,由于网络拥挤或一次发送的数据量过大等原因,经常会发生交换的数据在短时间内不能传送完,收发数据的函数因此不能返回,这种现象叫作阻塞。W I N SOCK对
10、有可能阻塞的函数提供了两种处理方式;阻塞和非阻塞方式。在阻塞方式(也称同步方式)下,收发数据的函数在被调用后一直要到传送完毕或者出错才能返回。由于操作可能需要任意长的时间才能完成。于是问题就出现了。最明显的一个例子就是recv(),这个函数会一直处于阻塞状态直到收到对方系统发送的数据。对于非阻塞方式,函数被调用后立即返回,当传送完成后W I N SOCK给程序发一个事先约定好的消息。63M icrocomputer Applications Vol.16,No.5,2000开发应用微型电脑应用2000年第16卷第5期在Berkeley套接口模型中,一个套接口的操作的缺省行为是阻塞方式的,除非程
11、序员显式地请求该操作为非阻塞方式。微软强烈推荐程序员在尽可能的情况下使用非阻塞方式(异步方式)的操作。因此非阻塞方式的操作能够更好地在非占先的W indow s环境下工作,程序员应该在绝对必要的时候才采用阻塞方式。如果一个正在运行某一阻塞操作的进程收到一个W in2dow s消息,那么应用程序有可能试图发出另一个W indow sSockets调用,由于很难安全地处理这种情形,W indow s Sock2ets规范不支持这种应用程序的工作方式。在这种情况下,有两个函数可以帮助程序员。W SA IsBlocking()可以用来确定在该进程上是否有阻塞的W indow s Sockets调用。W
12、 SACancel2BlookingCall()可以用来取消在线的阻塞调用,如果有的话。任何其他的W indow s Sockets函数如果在这种情况下被调用,则会失败并返回错误代码W SA E I N PROGRESS。要强调的是,这一限制适用于所有阻塞和非阻塞的操作。为了避免阻塞操作的缺点,我们可以使用多线程编程来实现。W I N SOCK通过异步选择函数W SAA syncSelect()来实现非阻塞通讯。方法是由该函数指定某种网络事件(如:有数据到达,可以发送数据,有程序请求连接等)当指定的网络事件发生时,由W I N SOCK对程序发送由程序事先约定的消息。程序中就可以根据这些消息做
13、相应的处理。格式如下:int W SAA syncSelect(SOCKETs,HWNDhwnd,un2signed int wM sg,long lEvent)sockets在这个函数调用中被自动设成非阻塞方式,hW nd是接收W I N SOCK消息的窗口句柄,非阻塞方式下,wM sg是向窗口发出消息名称,用户可以任意定义。lEvent是被指定的网络事件,有下面几种选择:FD-READ希望在Socket收到数据时收到消息;FD-WR ITE在可以发送数据时收到消息;FD-ACCEPT在有连接请求到达时收到消息;FD-CONN ECT在连接成功时收到消息;FD-CLOSE在连结关闭时收到的消
14、息。当被指定的事件发生时,程序将收到消息,消息的M SG结构体中,M essage项就是被规定的消息名称wM sg,lParam项中的内容就是与上面完全一样的网线络事件名称。有一点要注意的是,在非阻塞状态下,connect()函数的返回值都SOCKET-ERROR,表示有可能无法与远端的服务器建立连接。为了把这种情况与其他的错误区分开,可以调用一个专门的函数W SA GetL astError()来检查产生SOCKET-ERROR的原因,如该函数的返回值是W SA EWOULDBLOCK就表示上述情况。这时,程序可以给用户一个提示,表明程序正试图与远方服务器建立连接,如果等待时间过长,用户可以
15、将其停止。四、多线程技术简介当在网络中传输的数据是较大的数据块进(如图象),常常会出现阻塞现象。为了避免出现这种情况,并且提高传输的效率,我们可以使用多线程来进行网络编程。32位W indow s环境下的W in32 A P I提供了开发多线程应用程序的接口函数,并且VC+6.0提供的标准C库也可以开发多线程应用程序,但是更为经常的是使用M FC类库进行多线程编程。M FC执行两种类型的线程,一种是工作线程(Worker Thread);另一种是用户界面线程(U ser-InterfaceThread)。这两种类型都使用同一W in32 A P I调用机制,而且V isual C+6.0的M
16、FC库提供的CW inThread类是进行多线程编程的基础。实际上,CW inApp类就是一个用户界面线程,它由CW inThread类派生,用于应用程序与用户的交互。有两种方法可以创建线程。M FC提供如下全局函数创建线程:A fxBeginThread(),用A fxBeginThread()可以创建一个线程,M FC提供两个版本的A fxBeginThread()分别用于创工作线程和用户界面线程。该函数创建一个线程对象,并返回对象的指针(利用这个指针可以完成一些用户想做的事情)。另外,你也可以显式地创建线程对象,这需要首先声明线程对象,然后调用CW inThread的成员函数CW inT
17、hread:CreateTherad()函数创建线程,由于M FC区分两种线程,因此创建线程的参数也是不同的,也正是不同的参数区分了不同的线程,这将在下面结合Sockets编程做详细说明。五、在VC6.0中用多线程开发套接字程序在实际编程中,我们一般采用面向对象技术,特别采用消息驱动机制实现多任务的W indow s编程思想,VC由于它的强大的功能而被广泛采用。11 用VC6.0开发套接字程序的基本步骤在VC+6.0中,我们可以用W indow s Sockets A P I来编写网络程序,更为普遍的是,我们使用M FC封装的CA syncSocket和CSocket两个类来进行网络编程,它把
18、与套接字有关的W indow s消息换为回调函数,CA syncSocket类比CSocket更加面向低层,使用比较灵活,但它对编程人员的要求也高,需要对网络了解的更多。CSocket是CA syncSocket的导出类,通过M FC中的CA rchive类的对象提供了更高层次的抽象,它封装了Socket实现中的许多细节,并将Socket与A rchive相结合,使用它与使用M FC中的文档串行化协议相类似,使用便利。一般我们使用简便的CSocket编程,其步骤如下:(1)构造套接字对象。(2)使用该对象构造基本的套接字,对于CSocket客户端对象,使用缺省参数Create;对于CSock2
19、et服务器对象,应指明一个端口号作为Greate的一个参数,用于监听。(3)建立客户端CSocket,调用CA syncSocket:Con2nect建立与服务器端的连接,服务器端套接字调用CA sync2Socket:L isten监听,并在收到客户端请求后调用CA sync2Socket:A ccept。(4)构造CSocketFile对象,并使CSocket对象与之关联。(5)构造CA rchive对象,用于接收或发送数据。(6)使用CA rchive对象来进行客户端与服务器端的套接字通信。(7)删除CA rchive,CSocketFile,CSocket对象。流程图73M icroc
20、omputer Applications Vol.16,No.5,2000开发应用微型电脑应用2000年第16卷第5期如图4所示:21 回调函数的使用为了使网络通信更加方便,CA syncSocket和CSocket提供了一些回调函数。主窗口通过调用这些回调函数来套接字的一些重要事件的来临。这些回调函数有OnReceive,On2Send,onConnect,OnA ccept,OnClose,它们可以通过在两个类中重载得到。这两个类仅仅是通过回调函数将消息转化为通知,具体的如何响应这些通知,还须我们自己来实现。void CReceSocket:OnReceive(int nErrorCode
21、)CA syncSocket:OnReceive(nErrorCode);Receive(lpBuf,int nBufL en,int nFlage=0)如果自己的类继承CA syncSocket,为了使通信更加便利,必须重载这些回调函数,如果自己的类继承CSocket,将由你根据情况自己决定是否重载它们。必须注意的是,CSocket对象从不调用OnSend OnConnect这两个通知函数,而只能调用Send函数来发送数据,直到发送完成有数据Send对返回,同样只能调用Connect函数来进行连接,当完成连接时(成功或失败)Connect将返回。31 利用多线程来开发网络通信CSocket类
22、的缺省方式阻塞方式,为了避免阻塞的种种缺点,可以使用多线程,可以在一个工作线程中处理数据的接收和发送,该工作线程可以在后台运行,套接字在工作线程中的阻塞不会影响主线程中的其他活动,这样主线程可以处理主窗口的消息映射,下面结合一个实例说明如何创建、执行一个套接字工作线程的过程,该线程创建一个套接字,然后与服务器(IP为202.194.20.250)进行连接,连接成功后向服务器发送一些数据。U I N T SocketProc(L PVO I D pParam)CSendV iew3pV iew=(CSendV iew3)pParam;CSocket3pSocket=new CSocket();p
23、Socket-Create();?构造CSocket对象?与服务器连接if(!pSocket-Connect(202.194.20.2505050)A fxM essageBox(cantconnect to the distines!)83M icrocomputer Applications Vol.16,No.5,2000开发应用微型电脑应用2000年第16卷第5期?构造CSocketFile对象,并使CSocket对象与之关联。CSocketFile3m-pFile=new CSocketFile(pSocket);?构造CA rchive对象,用于发送数据。CA rchive3m-p
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 多线程 实现 Winsock 编程
限制150内