網絡編程實用教程_第5章 MFC WinSock類的編程_第1頁
網絡編程實用教程_第5章 MFC WinSock類的編程_第2頁
網絡編程實用教程_第5章 MFC WinSock類的編程_第3頁
網絡編程實用教程_第5章 MFC WinSock類的編程_第4頁
網絡編程實用教程_第5章 MFC WinSock類的編程_第5頁
已閱讀5頁,還剩43頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

1、第第5章章 MFC WinSock類的編程類的編程 為簡化套接字網絡編程,更方便地利用Windows的消息驅動機制,微軟的基礎類庫(Microsoft Foundation Class Libary,簡稱MFC),提供了兩個套接字類,在不同的層次上對Windows Socket API函數進行了封裝,為編寫Windows Socket網絡通信程序,提供了兩種編程模式。 CAsyncSocket類,在很低的層次上對Windows Sockets API進行了封裝。 它的成員函數和Windows Sockets API的函數調用直接對應。一個CAsyncSocket對象代表了一個Windows套接

2、字。它是網絡通信的端點。除了把套接字封裝成C+的面向對象的形式供程序員使用以外,這個類唯一所增加的抽象就是將那些與套接字相關的Windows消息變?yōu)镃AsyncSocket類的回調函數。 CSocket類,從CAsyncSocket類派生,是對Windows Sockets API的高級封裝。CSocket類繼承了CAsyncSocket類的許多成員函數,用法一致。CSocket類的高級表現在三個方面:(1)CSocket結合archive類來使用套接字。(2)CSocket管理了通信的許多方面,如字節(jié)順序問題和字符串轉換問題。 (3)CSocket類為Windows消息的后臺處理提供了阻塞的

3、工作模式。 這兩個類提供了事件處理函數,編程者通過對事件處理函數進行重載,可方便地對套接字發(fā)送數據、接收數據等事件進行處理。同時,可以結合MFC的其它類來使用這兩個套接字類,并利用MFC的各種可視化向導,從而大大簡化了編程。 在MFC中,有一個名為afxSock.h的包含文件,在這個文件中定義了CAsyncSocket,CSocket,和CSocketFile這三個套接字類。 5.1 CasyncSocket類類CAsyncSocket類從Cobject類派生而來,如圖5.1所示: 圖5.1 CAsyncSocket類的派生關系 5.1.1 使用使用CAsyncSocket類的一般步驟類的一般

4、步驟網絡應用程序一般采用客戶/服務器模式,它們使用使用CAsyncSocket類編程的步驟有所不同,參看表5.1。 序號服務器(Server)客戶機(Client)1/構造一個套接字ACsyncSocket sockSrvr;/構造一個套接字ACsyncSocket sockClient;2/創(chuàng)建Socket句柄到指定端口sockSrvr.Create(nPort);/創(chuàng)建Socket句柄,參數默認sockClient.Create();3/啟動監(jiān)聽,準備接受請假sockSrvr.Listen();4/請求連接到服務器sockClient.Connect()5.1.2 創(chuàng)建創(chuàng)建CasyncSo

5、cket類對象類對象 本書將CAsyncSocket類對象稱為異步套接字對象。創(chuàng)建異步套接字對象一般分為兩個步驟,首先構造一個CAsyncSocket對象,再創(chuàng)建該對象的底層的SOCKET句柄。1創(chuàng)建空的異步套接字對象創(chuàng)建空的異步套接字對象 通過調用CAsyncSocket類的構造函數,創(chuàng)建一個新的空CAsyncSocket類套接字對象,構造函數不帶參數。然后必須調用它的Create成員函數,來創(chuàng)建底層的套接字數據結構,并綁定它的地址。 有兩種使用方法,會在不同的位置創(chuàng)建。(1)如:CAsyncSocket aa; aa.Create(。);(2)如: CAsyncSocket* Pa; Pa

6、 = new CAsyncSocket; Pa-Create(。); 2創(chuàng)建異步套接字對象的底層套接字句柄創(chuàng)建異步套接字對象的底層套接字句柄通過調用CAsyncSocket類的Create()成員函數,創(chuàng)建該對象的底層套接字句柄,決定套接字對象的具體特性。調用格式為:BOOL Create( UINT nSocketPort=0, Int nSocketType = SOCK_STREAM, Long Ievent = FD_READ | FD_WRITE | FD_OOB | FD_ACCEPT |FD_CONNECT | FD_CLOSE, LPCTSTR lpszSocketAddres

7、s = NULL ); 舉例:創(chuàng)建一個使用27端口的流式異步套接字對象。CAsyncSocket* pSocket = new CAsyncSocket;int nPort = 27;pSocket-Create( nPort, SOCK_STREAM ); 5.1.3 關于關于CAsyncSocket類可以接受并處理的類可以接受并處理的消息事件消息事件1六種套接字相關的事件與通知消息六種套接字相關的事件與通知消息參數Ievent可以選用的六個符號常量是在winsock.h文件中定義的。#define FD_READ 0 x01#define FD_WRITE 0 x02#define FD_

8、OOB 0 x04#define FD_ACCEPT 0 x08#define FD_CONNECT 0 x10#define FD_CLOSE 0 x20 他們代表MFC套接字對象可以接受并處理的六種網絡事件,當事件發(fā)生時,套接字對象會收到相應的通知消息,并自動執(zhí)行套接字對象響應的事件處理函數。(1)FD_READ事件通知:通知有數據可讀。(2)FD_WRITE事件通知:通知可以寫數據。(3)FD_ACCEPT事件通知:通知監(jiān)聽套接字有連接請求可以接受。(4)FD_CONNECT事件通知:通知請求連接的套接字,連接的要求已被處理。(5)FD_CLOSE事件通知:通知套接字已關閉。(6)FD_

9、OOB事件通知:通知將有帶外數據到達。 2MFC框架對于六個網絡事件的處理框架對于六個網絡事件的處理當上述的網絡事件發(fā)生時,MFC框架作何處理呢?按照Windows的消息驅動機制,MFC框架應當把消息發(fā)送給相應的套接字對象,并調用作為該對象成員函數的事件處理函數。事件與處理函數是一一映射的。 在afxSock.h文件中的CAsyncSocket類的聲明中,定義了與這六個網絡事件對應的事件處理函數。virtual void OnReceive(int nErrorCode); 對應 FD_READ事件virtual void OnSend(int nErrorCode); 對應 FD_WRITE

10、事件virtual void OnAccept(int nErrorCode); 對應 FD_ACCEPT事件virtual void OnConnect(int nErrorCode); 對應 FD_CONNECT事件virtual void OnClose(int nErrorCode); 對應 FD_CLOSE事件virtual void OnOutOfBandData(int nErrorCode); 對應 FD_OOB事件 當某個網絡事件發(fā)生時,MFC框架會自動調用套接字對象的對應的事件處理函數。這就相當給了套接字對象一個通知,告訴它某個重要的事件已經發(fā)生。所以也稱之為套接字類的通知

11、函數(notification functions)或回調函數(callback functions)。 3重載套接字對象的回調函數重載套接字對象的回調函數如果你從CAsyncSocket類派生了自己的套接字類,你必須重載你的應用程序所感興趣的那些網絡事件所對應的通知函數。MFC框架自動調用通知函數,使得你可以在套接字被通知的時候來優(yōu)化套接字的行為。 5.1.4 客戶端套接字對象請求連接到服務器客戶端套接字對象請求連接到服務器端套接字對象端套接字對象 在服務器端套接字對象已經進入監(jiān)聽狀態(tài)之后,客戶應用程序可以調用CAsyncSocket類的Connect()成員函數,向服務器發(fā)出一個連接請求

12、格式一: BOOL Connect( LPCTSTR lpszHostAddress, UINT nHostPort );格式二: BOOL Connect( const SOCKADDR* lpSockAddr, int nSockAddrLen ); 如果調用成功或者發(fā)生了WSAEWOULDBLOCK錯誤,當調用結束返回時,都會發(fā)生FD_CONNECT事件,MFC框架會自動調用客戶端套接字的OnConnect()事件處理函數,并將錯誤代碼作為參數傳送給它。它的原型調用格式如下: virtual void OnConnect( int nErrorCode ); 5.1.5 服務器接受客戶機

13、的連接請求服務器接受客戶機的連接請求在服務器端,使用CAsyncSocket流式套接字對象,一般按照以下步驟來接收客戶端套接字對象的連接請求。(1)服務器應用程序必須首先創(chuàng)建一個CAsyncSocket流式套接字對象,并調用它的Create成員函數創(chuàng)建底層套接字句柄。這個套接字對象專門用來監(jiān)聽來自客戶機的連接請求,所以稱它為監(jiān)聽套接字對象。 (2)調用監(jiān)聽套接字對象的Listen成員函數,使監(jiān)聽套接字對象開始監(jiān)聽來自客戶端的連接請求。此函數的調用格式是: BOOL Listen( int nConnectionBacklog = 5); 當Listen函數確認并接納了一個來自客戶端的連接請求后

14、,會觸發(fā)FD_ACCEPT事件,監(jiān)聽套接字會收到通知,表示監(jiān)聽套接子已經接納了一個客戶的連接請求,MFC框架會自動調用監(jiān)聽套接字的OnAccept事件處理函數,它的原型調用格式如下: virtual void OnAccept( int nErrorCode );編程者一般應重載此函數,在其中調用監(jiān)聽套接字對象的Accept函數,來接收客戶端的連接請求。 (3)創(chuàng)建一個新的空的套接字對象,不需要使用它的Create函數來創(chuàng)建底層套接字句柄。這個套接字專門用來與客戶端連接,并進行數據的傳輸。一般稱它為連接套接字,并作為參數傳遞給下一步的Accept成員函數。 (4)調用監(jiān)聽套接字對象的Accep

15、t成員函數,調用格式為:virtual BOOL Accept( CAsyncSocket& rConnSocket,SOCKADDR* lpSockAddr = NULL,int* lpSockAddrLen = NULL );5.1.6 發(fā)送與接收流式數據。發(fā)送與接收流式數據。當服務器和客戶機建立了連接以后,就可以在服務器端的連接套接字對象和客戶端的套接字對象之間傳輸數據了。對于流式套接字對象,使用CAsyncSocket類的Send成員函數向流式套接字發(fā)送數據,使用Receive成員函數從流式套接字接收數據。 1用用Send成員函數發(fā)送數據成員函數發(fā)送數據格式:virtual i

16、nt Send( const void* lpBuf, int nBufLen, int nFlags = 0); 對于一個CAsyncSocket套接字對象,當它的發(fā)送緩沖區(qū)騰空時,會激發(fā)FD_WRITE事件,套接字會得到通知,MFC框架會自動調用這個套接字對象的OnSend事件處理函數。一般編程者會重載這個函數,在其中調用Send成員函數來發(fā)送數據。 2用用Receive成員函數接收數據成員函數接收數據格式: Virtual int Receive( Void* lpBuf, int nBufLen, Int nFlags = 0); 對于一個CAsyncSocket套接字對象,當有數據到

17、達它的接收隊列時,會激發(fā)FD_READ事件,套接字會得到已經有數據到達的通知,MFC框架會自動調用這個套接字對象的OnReceive事件處理函數。一般編程者會重載這個函數,在其中調用Receive成員函數來接收數據。在應用程序將數據取走之前,套接字接收的數據將一直保留在套接字的緩沖區(qū)中。 5.1.7 關閉套接字關閉套接字1使用使用CAsyncSocket類的類的Close成員函數成員函數格式:virtual void Close( );2使用使用CAsyncSocket類的類的ShutDown()成成員函數員函數 使用CAsyncSocket類的ShutDown()成員函數,可以選擇關閉套接字

18、的方式。將套接字置為不能發(fā)送數據,或不能接收數據,或二者均不能的狀態(tài)。格式:BOOL ShutDown( int nHow = sends ); 5.1.8 錯誤處理錯誤處理 一般說來,調用CAsyncSocket對象的成員函數后,返回一個邏輯型的值,如果成員函數執(zhí)行成功,返回TRUE;如果失敗,返回FALSE。究竟是什么原因造成錯誤呢?這時,可以進一步調用CAsyncSocket對象的GetLastError()成員函數,來獲取更詳細的錯誤代碼,并進行相應的處理。格式: static int GetLastError( );返回值是一個錯誤碼,針對剛剛執(zhí)行的CAsyncSocket成員函數。

19、 5.1.9 其它的成員函數其它的成員函數1關于套接字屬性的函數關于套接字屬性的函數要 設 置 底 層 套 接 字 對 象 的 屬 性 , 可 以 調 用SetSocketOpt()成員函數;要獲取套接字的設置信息,可調用GetSocketOpt()成員函數;要控制套接字的工作模式,可調用IOCtl()成員函數,選擇合適的參數,可以將套接字設置在阻塞模式(Blocking mode)下工作。 2發(fā)送和接收數據發(fā)送和接收數據如果創(chuàng)建的是數據報類型的套接字,用SendTo()成員函數來向指定的地址發(fā)送數據,事先不需要建立發(fā)送端和接收端之間的連接,用ReceiveFrom()成員函數可以從某個指定的

20、網絡地址接收數據。 發(fā)送數據SendTo的調用格式,有兩種重載的形式,區(qū)別在于參數不同:int SendTo( const void* lpBuf, int nBufLen, UINT nHostPort, LPCTSTR lpszHostAddress = NULL, int nFlags = 0 );int SendTo( const void* lpBuf, int nBufLen, const SOCKADDR* lpSockAddr, int nSockAddrLen, int nFlags = 0 );接收數據ReceiveFrom的調用格式,也有兩種重載的形式,區(qū)別在于參數不同:

21、int ReceiveFrom( void* lpBuf, int nBufLen, CString& rSocketAddress, UINT& rSocketPort, int nFlags = 0 );int ReceiveFrom( void* lpBuf, int nBufLen, SOCKADDR* lpSockAddr, int* lpSockAddrLen, int nFlags = 0 ); 5.2 CSocket類類CSocket類是從CAsyncSocket類派生而來的,它們的派生關系如圖5.2: 圖5.2 CSocket類的派生關系 5.2.1 創(chuàng)建創(chuàng)建

22、CSocket對象對象分為兩個步驟:(1)調用CSocket類的構造函數,創(chuàng)建一個空的CSocket對象。(2)調用此CSocket對象的Create()成員函數,創(chuàng)建對象的底層套接字。調用格式是:BOOL Create( UINT nSocketPort = 端口號,Int nSocketPort = SOCK_STREAM | SOCK_DGRAM,LPCTSTR lpszSocketAddress = 套接字所用的網絡地址 );如果打算使用CArchive對象和套接字一起進行數據傳輸工作,必須使用流式套接字。 5.2.2 建立連接建立連接 CSocket類使用基類CAsyncSocket

23、的同名成員函數Connect()、Listen()、Accept()來建立服務器和客戶機套接字之間的連接,使用方法相同。不同的是:CSocket類的Connect()和Accept()支持阻塞調用。比如:在調用Connect()函數時會發(fā)生阻塞,直到成功地建立了連接或有錯誤發(fā)生才返回,在多線程的應用程序中,一個線程發(fā)生阻塞,其他的線程仍能處理Windows事件。 CSocket對象從不調用OnConnect()事件處理函數。 5.2.3 發(fā)送和接收數據。發(fā)送和接收數據。 在創(chuàng)建CSocket類對象后,對于數據報套接字,直接使用CSocket類的SendTo()、ReceiveFrom()成員函

24、數來發(fā)送和接收數據。對于流式套接字,首先在服務器和客戶機之間建立連接,然后使用CSocket類的Send()、Receive()成員函數來發(fā)送和接收數據,它們的調用方式與CAsyncSocket類相同。 不同的是:CSocket類的這些函數工作在阻塞的模式。比如,一旦調用了Send()函數,在所有的數據發(fā)送之前,程序或線程將處于阻塞的狀態(tài)。一般將CSocket類與CArchive類和CSocketFile類結合,來發(fā)送和接收數據,這將使編程更為簡單。CSocket對象從不調用OnSend()事件處理函數。 5.2.4 CSocket類與類與CArchive類和類和CSocketFile類類 使

25、用CSocket類的最大優(yōu)點在于,應用程序可以在連接的兩端通過CArchive對象來進行數據傳輸。具體做法是:(1)創(chuàng)建CSocket類對象(2)創(chuàng)建一個基于CSocketFile類的文件對象,并把它的指針傳給上面的已創(chuàng)建的CSocket對象。(3)分別創(chuàng)建用于輸入和輸出的CArchive對象,并將它們與這個CSocketFile文件對象連接。(4)利用CArchive對象來發(fā)送和接收數據。 下面是一段示例代碼:CSocket exSocket;/ 創(chuàng)建一個空的CSocket對象CSocketFile* pExFile;/定義一個CSocketFile對象指針/ 定義一個用于輸入的Carchi

26、ve對象指針CArchive* pCArchiveIn; / 定義一個用于輸出的Carchive對象指針CArchive* pCArchiveOut;/ 創(chuàng)建Csocket對象的底層套接字exSocket.Create();/創(chuàng)建CSocketFile對象,并將CSocket對象的指針傳遞給它pExFile = new CSocketFile( & exSocket,TRUE);/創(chuàng)建用于輸入的CArchive對象pCArchiveIn = new CArchive(pExFile, CArchive:load);/創(chuàng)建用于輸出的CArchive對象。pCArchiveOut = ne

27、w CArchive(pExFile, CArchive:store); 圖5.3 CSocket、CArchive和CSocketFile類在傳輸數據時的作用 5.2.5 關閉套接字和清除相關的對象,關閉套接字和清除相關的對象,在使用完CSocket對象以后,應用程序應調用它的Close()成員函數來釋放套接字占用的系統(tǒng)資源,也可以調用它的ShutDown()成員函數來禁止套接字讀寫。而對于相應的CArchive對象、CSocketFile對象和CSocket對象,可以將它們銷毀;也可以不作處理,因為當應用程序終止時,會自動調用這些對象的析構函數,從而釋放這些對象占用的資源。 5.3 CSocket類的編程模型類的編程模型下面給出針對流式套接字的CSocket類的編程模型。分為服務器端和客戶端。1服務器端服務器端 CSocket sockServ; /創(chuàng)建空的服務器端監(jiān)聽套接字對象 sockSer

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論