對MFC封裝Windows通訊API的研究 (轉)

worldblog發表於2007-12-07
對MFC封裝Windows通訊API的研究 (轉)[@more@]

一、引言
  Inte進行網際間通訊,在WWW瀏覽、、Gopher這些常規服務,以及在電話、多會議等這些對實時性要求嚴格的應用中成為研究的熱點,而且已經是必需的了。環境下進行通訊設計的最基本方法是應用WindowsSockets實現程式間的通訊,為此提供了大量基於WindowsSockets的通訊,如WinSockAPI、WinInetAPI和ISAPI,並一直致力於開發更快、更容易的通訊API,將其和MFC整合在一起以使通訊越來越容易。
  MFC是VC程式設計環境最重要的組成部分,它為提供了一大批預先定義的類和成員,封裝了大量的WindowsAPI。同時VC環境提供了與MFC和程式碼一起工作的專用工具:AppStudio源程式編輯器、AppWizard和ClassWizard。應用MFC,可以使Windows程式設計師用較少的時間和精力開發出複雜的通訊應用程式。

  本文根據筆者自己在開發實時網路工具FreeTalk過程中的一些,介紹Windows環境下的常用API和封裝它們的MFC類,重點介紹使用MFC的CAsyncsocket和CSocket類編寫網路通訊程式的方法,這兩個類封裝了WinSockAPI,並使他們更容易使用和更適應於MFC程式設計環境。

二、Windows環境下的通訊API和相應的MFC類
  1.WindowsSockets(WinSock)API
  WindowsSockets定義了Windows的網路程式設計介面,它基於加利福尼亞大學伯克利分校的伯克利Sockets。WindowsSockets既包括風格的例程,還加入了Windows的擴充套件部分,例如用於訊息的擴充套件函式。WindowsSockets可以執行在許多網路之上,包括、XNS、DECNet、IPX/SPX等。在環境下,WindowsSockets提供執行緒。透過微軟與標準組織的努力,為WinSock定義了應用程式設計介面(WinSockAPI),可以非常方便地利用下層的網路協議(如TCP/IP)進行網路通訊。

  透過提供兩個類CAsyncSocket和CSocket,MFC支援使用WinSockAPI通訊程式設計。MFC把複雜的WinSockAPI封裝到類裡,這使得編寫應用程式更容易。CAsyncSocket類逐個封裝了WinSockAPI,為高階網路程式設計師提供了更加有力而靈活的方法。這個類基於程式設計師瞭解網路通訊的假設,目的是為了在MFC中使用WinSock,程式設計師有責任處理諸如阻塞、位元組順序和在Unicode與MBCS間轉換字元的任務。為了給程式設計師提供更方便的介面以自動處理這些任務,MFC給出了CSocket類,這個類是由CAsyncSocket類繼承下來的,它提供了比CAsyncSocket更高層的WinSockAPI介面。Csocket類和CsocketFile類與Carchive類一起合作來管理傳送和接收的資料,這使管理資料收發更加便利。CSocket物件提供阻塞,這對於Carchive的同步操作是至關重要的。阻塞函式[比如Receive()、Send()、ReceiveFrom()、SendTo()和Accept()]直到操作完成後才返回控制權,因此如果需要低層控制和高,就使用CasyncSock類;如果需要方便,則可使用Csocket類。2.Win32Internet(WinInet)API

  微軟公佈了一些使Internet應用程式的設計比以前更快、更容易的API:WinInetAPI,它提供了中高層通訊函式,這使訪問主要的Internet協議變得相當容易。這些函式在程式設計師和WinSock驅動之間提供了隔離層。有4類WinInetAPI函式:通用WinInet函式、WinInet傳輸協議(FTP)函式、WinInetGopher函式、WinInet超文字傳輸協議(HTTP)函式。

  事實上,MFC把WinInetAPI和技術封裝進類,使Internet程式設計更加容易,這些類包括CInternetSession、CInternetConnection、CInternetFile、CHttpConnection、CHttpFile、CGopherFile、CFtpConnection、CGopherConnection、CFileFind、CFtpFileFind、CGopherFileFind、CGopherLocator和CInternetException。

  3.InternetAPI(ISAPI)

  微軟的IIS是惟一與WindowsNTServer操作緊密整合的WWW伺服器,它作為Internet/Intranet伺服器應用範圍很廣。IIS允許擴充套件功能,這是透過ISAPI來實現的,ISAPI描述了與Internet伺服器之間的介面。用ISAPI提供的工具,可建立高、高效率、滿足商業安全及符合新的IIS標準的Internet伺服器。同樣,ISAPI在MFC中由典型的類所封裝,包括CHttpFilter、CHttpFilterContext、CHttpServer、CHttpServerContext、RelatedClasses和CHtmlStream。

三、WinSockAPI的MFC封裝類
  一些網路應用程式(如網路電話、多媒體會議工具)實時性要求非常強,要求能夠直接應用WinSock傳送和接收資料。這時設計者應該選擇直接應用WinSockAPI或者由MFC封裝的WinSockAPI。新開發的應用程式中,為了充分利用MFC的優勢,首選方案應當是MFC中的CAsyncSocket類和CSocket類,這兩個類完全封裝了WinSockAPI,並提供更多的便利。本文介紹應用這兩個類的程式設計模型,並引出相關的成員函式與一些概念的解釋。
  1.CAsyncSocket類和CSocket類簡述
  CAsyncSocket類和CSocket類的繼承關係由附圖給出。CSocket類是由CAsyncSocket繼承而來的,事實上,在MFC中CAsyncSocket逐個封裝了WinSockAPI,每個CAsyncSocket物件代表一個WindowsSocket,使用CAsyncSocket類要求程式設計師對網路程式設計較為熟悉。相比起來,CSocket類是CAsyncSocket的派生類,繼承了它封裝的WinSockAPI。一個CSocket物件代表了一個比CAsyncSocket物件更高層次的WindowsSocket抽象,CSocket類與CSocketFile類和CArchive類一起工作來傳送和接收資料,因此使用它更加容易。CSocket物件提供阻塞模式,因為阻塞功能對於CArchive的同步操作是至關重要的。在這裡有必要對阻塞的概念作一解釋:一個socket可以處於“阻塞模式”或“非阻塞模式”,當一個套接字處於阻塞模式(即同步操作)時,它的阻塞函式直到操作完成才會返回控制權,之所以稱為阻塞是因為此套接字的阻塞函式在完成操作返回之前什麼也不能做。如果一個socket處於非阻塞模式(即非同步操作),則會被函式立即返回。在CAsyncSocket類中可以用GetLastError成員函式查詢最後的錯誤,如果錯誤是WSAEWOULLOCK則說明有阻塞,而CSocket絕不會返回WSAEWOULDBLOCK,因為它自己管理阻塞。微軟建議儘量使用非阻塞模式,透過網路事件的發生而通知應用程式進行相應的處理。但在CSocket類中,為了利用CArchive處理通訊中的許多問題和簡化程式設計,它的一些成員函式總是具有阻塞性質的,這是因為CArchive類需要同步的操作。在Win32環境下,如果要使用具有阻塞性質的套接字,應該放在獨立的工人執行緒中處理,利用多執行緒的方法使阻塞不至於干擾其他執行緒,也不會把時間浪費在阻塞上。多執行緒的方法既可以使程式設計師享受CSocket帶來的簡化程式設計的便利,也不會影響使用者介面對使用者的反應。

  2.CAsyncsocket類程式設計模型

  在一個MFC應用程式中,要想輕鬆處理多個網路協議,而又不犧牲靈活性時,可以考慮使用CAsyncSocket類,它的效率比CSocket類要高。CAsyncSocket類針對位元組流型套接字的程式設計模型簡述如下:

  (1)構造一個CAsyncSocket物件,並用這個物件的Create成員函式產生一個Socket控制程式碼。可以按如下兩種方法構造:

CAsyncSocketsock;
Sock.Create();
用預設引數產生一個位元組流套接字

CAsyncSocket*pSocket=newCAsyncSocket;
intnPort=27;
pSocket->Create(nPort,SOCK-DGRAM);
定埠號產生一個資料包套接字

  第一種方法在棧上產生一個CAsyncSocket物件,而第二種方法在堆上產生CAsyncSocket物件。第一種Create成員函式用預設引數產生一個位元組流套接字,第二種Create成員函式用指定的埠和地址產生一個數字報套接字。Create的引數有:
  ①埠,UINT型別。注意:如果是服務方,則使用一個眾所周知的埠供服務方連線;如果是客戶方,典型做法是接受預設引數,使套接字可以自主選擇一個可用埠;

  ②socket型別。SOCK-STREAM(預設值)或SOCK-DGRAM;

  ③socket地址。例如“”或“202.193.64.33”。

  (2)如是客戶方程式,用CAsyncSocket∷Connect成員函式連線到服務方;如是服務方程式,用CAsyncSocket∷Listen成員函式開始,一旦收到連線請求,則呼叫CAsyncSocket∷Accept成員函式開始接收。注意:CAsyncSocket∷Accept成員函式要用一個新的並且是空的CSocket物件作為它的引數,這裡所說的“空的”指的是這個新物件還沒有呼叫Create成員函式。

  (3)呼叫其他的CAsyncSocket類成員函式進行通訊管理。

  (4)通訊結束後,銷燬CAsyncSocket物件。如果是在棧上產生的CAsyncSocket物件,則物件超出定義的範圍時自動被析構;如果是在堆上產生,也就是用了new這個運算子,則必須使用delete運算子銷燬CAsyncSocket物件。

  3.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物件在客戶與服務方傳送資料。(7)通訊完畢後,銷燬CArchive、CSocketFile和CSocket物件。


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752043/viewspace-989394/,如需轉載,請註明出處,否則將追究法律責任。

相關文章