1 . WinSock API
Windows Sockets 是在 Windows 環境下使用的一套網絡編程規范,常常簡稱為 Winsock 。
WinSock 主要是基于 socket 來開發基于 TCP/IP 模型中各層的服務器端與客戶端程序。可使用 RAW SOCKET API (原始套接字)開發低層協議的程序,當然這需要了解協議的報文格式。
1.1 Windows Sockets API
參考《 WinSock 編程基礎 》中的 Windows Sockets 規范。
1.2 Winsock API 函數的分類
在 Winsock 規范中把 Winsock API 函數集分為與 BSD Socket( 用在 Unix 中 ) 相兼容的基本函數、網絡數據信息檢索函數和 Windows 專用擴展函數三類。
參考《 WinSock 編程基礎 》中的套接字 API 概覽。
2 . CAsyncSocket/CSocket
2.1 MFC 對 Winsock API 的封裝( Windows Sockets: Using Class CAsyncSocket )
CAsyncSocket 對象表示一個 Windows Socket-- 一個網絡通信的端點。 CAsyncSocket 類封裝了 Windows 套接字 API ,對想使用與 MFC 連接的 Windows 套接字的程序員提供了一個面向對象的抽象化概念。它是基于暗窗口的 WSAAsyncSelcet 異步 I/O 模型。所謂 “ 暗窗口 ” 是指委托處理網絡事件消息的窗口,即 "Socket Notification Sink" 。由于暗窗口只是用來在后臺做消息處理,故其風格、尺寸都為零,隱而不顯。
應用此類,需處理塊、字節順序(大小端)以及 Unicode 和多字符集( MBCS )的問題。如果想要一個更方便的處理這些問題的接口,參閱 CSocket 類。
與 CAsyncsocket 對象相比, CSocket 對象代表了 Windows Sockets API 的更高一級的抽象化。 CSocket 與類 CSocketFile 和 CArchive 一起來管理對數據的發送和接收。
CAsyncSocket & CSocket
2.2 CAsyncsocket
聲明一個 CAsyncSocket 對象后,需調用 Create 成員函數進行具體套接字的創建: CAsyncSocket :: Create à CAsyncSocket :: Socket à CAsyncSocket :: AttachHandle / CAsyncSocket :: AsyncSelect 。
CAsyncSocket :: AttachHandle 完成 MFC 對象 CAsyncSocket 與 SOCKET 內核對象(句柄)的附加委托。
使用 CAsyncSocket 的線程在創建第一個對象時, _AFX_SOCK_THREAD_STATE :: m_pmapSocketHandle -> IsEmpty () == TRUE, 將創建一個暗窗口( CSocketWnd 對象)并記錄在線程套接字狀態管理模塊的 m_hSocketWindow 字段中( _AFX_SOCK_THREAD_STATE :: m_hSocketWindow )。
在 CAsyncSocket :: AsyncSelect 中,調用 WSAAsyncSelect ( m_hSocket , pState -> m_hSocketWindow , WM_SOCKET_NOTIFY , lEvent ) 。
以后該線程的所有 CAsyncSocket 對象的網絡事件均以消息 WM_SOCKET_NOTIFY 發送給 _AFX_SOCK_THREAD_STATE :: m_hSocketWindow 。
暗窗口 CSocketWnd 接收 WM_SOCKET_NOTIFY 消息,消息處理函數 OnSocketNotify 被調用 — ON_MESSAGE ( WM_SOCKET_NOTIFY , OnSocketNotify ) 。
WM_SOCKET_NOTIFY 消息的 wParam 參數為對應發生該事件的套接字句柄, lParam 參數的高字位 ( 一般用 WSAGETSELECTERROR 宏取得 HIWORD) 包含出錯碼, lParam 參數的低字位 ( 一般用 WSAGETSELECTEVENT 宏取得 LOWORD) 則標識了網絡事件代碼 (FD_XXX) 。一般先檢查高位,再檢查低位進行網絡事件的處理。
OnSocketNotify 函數回調 CAsyncSocket :: DoCallBack , DoCallBack 調用事件處理函數,如 OnRead 、 OnWrite 等。 OnRead 、 OnWrite 在 CAsyncSocket 中為空,用戶一般需要重載虛函數 OnRead 、 OnWrite ,調用 Receive 、 Send 進行接發處理。 Receive 、 Send 只是對 recv 和 send 的簡單調用,它們都是可重載的虛函數。
2.3 CSocket
CSocket 類是從 CAsyncsocket 派生的一個 同步阻塞 Socket 的封裝類, CSocket 類的諸如 Send() , Receive() 在收到 WSAEWOULDBLOCK“ 錯誤 ” 時,不是如 CAsyncSocket 那樣立即返回,而是 進入 PumpMessages() 消息循環 , PumpMessages() 直到有指定事件( uStopFlag == FD_* )發生才返回,在 2 秒( CSocket :: m_nTimeOut ) 期間,如果線程取到了任一窗口的 WM_PAINT 消息,則刷新相應窗口。這樣異步的 CAsyncSocket ,到了派生類 CSocket ,就變成同步的了。
2.4 多線程環境下的 CAsyncSocket/CSocket
CAsyncSocket/CSocket 不是線程安全的,典型的在一個線程里調用了 CSocket 的成員函數,之后啟動一個線程,在另一線程中對 CSocket 對象調用成員函數會失敗,提示 SOCKET 相關的窗口不存在。其原因在于消息循環是和窗口相關的,而窗口又是線程相關的。具體涉及到 SOCKET 狀態 _AFX_SOCK_STATE 和 SOCKET 線程模塊狀態 _AFX_SOCK_THREAD_STATE ( AFX_MODULE_THREAD_STATE )。
CSocket 一般配合多線程使用,只要你想收發數據,你就可以創建一個 CSocket 對象,并創建一個子線程來進行收發。同步 + 多線程 ≈ 異步。但是大規模并發通信時,由于 Windows 消息泵本省的局限性, WAsyncSelect 異步模型可能遭遇瓶頸。
最后,別忘了使用 MFC WinSock 類 CAsyncSocket/CSocket 的線程需要調用 AfxSocketInit 初始化 WinSock 庫。一般在 MFC 程序的 CWinApp :: InitInstance () 中調用 AfxSocketInit 。
源碼參考 : <AFXSOCK.H> 、 <AFXSOCK.INL> 、 <SOCKCORE.CPP>
// AFXSOCK.H
#include <winsock.h>
#pragma comment(lib, "wsock32.lib")
/////////////////////////////////////////////////////////////////
// AFXSOCK - MFC support for Windows Sockets
// CSocketWnd -- internal use only Implementation for sockets notification callbacks.
class CSocketWnd : public CWnd
// Async Socket implementation and base class for Synchronous Socket
class CAsyncSocket : public CObject
// Synchronous Socket
class CSocket : public CAsyncSocket
// Used with CSocket and CArchive for streaming objects on sockets.
class CSocketFile : public CFile
3 . WinInet API
WinInet API 主要是開發基于 TCP/IP 模型中的應用層 客戶端 程序。
WinInet (「 Windows Internet 」) API 是一個高階函數集,幫助程序寫作者使用三個常見的 Internet 協議:用于 World Wide Web 全球信息網的超文字傳輸協議( HTTP , Hypertext Transfer Protocol )、文件傳輸協議( FTP , File Transfer Protocol )和另一個稱為 Gopher 的文件傳輸協議。
WinInet API 由動態鏈接庫 wininet.dll 提供支持。
// Internet Extensions for Win32
#include <wininet.h>
#pragma comment (lib, "wininet.lib")
LoadLibrary ("C://WINDOWS//system32//wininet.dll");
WinInet 函數的語法與常用的 Windows 文件函數的語法類似,這使得使用這些協議就像使用本地磁盤驅動器上的文件一樣容易。
MFC 對 WinInet API 的封裝( MFC Classes for Creating Internet Client Applications )
MSDN 關鍵字 : WinInet, programming/ WinInet, classes
MFC provides the following classes and global functions for writing Internet client applications . Indentation indicates a class is derived from the unindented class above it. CGopherFile and CHttpFile derive from CInternetFile , for example.
Classes:
CInternetSession
CInternetConnection
CFtpConnection
CGopherConnection
CHttpConnection
CInternetFile
CGopherFile
CHttpFile
CFileFind
CFtpFileFind
CGopherFileFind
CGopherLocator
CInternetException
Global functions:
AfxParseURL
AfxGetInternetHandleType
AfxThrowInternetException
源碼參考 : <AFXINET.H> 、 <AFXINET.INL> 、 <INET.CPP>
// AFXINET.H
#include <wininet.h>
#pragma comment(lib, "wininet.lib")
// Global Functions
AfxParseURL ();
AfxParseURLEx ();
CHtmlView
class CHtmlView : public CFormView
CHtmlView 類在文檔 / 視圖結構的應用程序中提供 WebBrowser 控件的功能。 WebBrowser 控件是客戶可瀏覽網址以及本地文件和網絡文件的窗口。 WebBrowser 控件支持超級鏈接、統一資源定位符( URL )導航器并維護一張歷史列表,核心接口是 IWebBrowser2 ,它是 Internet Explorer 的核心。
源碼參考 : <AFXHTML.H> 、 <AFXHTML.INL> 、 <VIEWHTML.CPP>
4.ISAPI
ISAPI 是 Internet Server Application Program Interface ( 服務器 應用程序接口)的簡寫,是微軟提供的一套面向 Internet 服務的 API 接口,它能實現 CGI ( Common Gateway Interface ,公共網關接口)能提供的全部功能,并在此基礎上進行了擴展,如提供了過濾器應用程序接口。 ISAPI 的工作原理和 CGI 大體上是相同的,都是通過交互式主頁取得用戶輸入信息,然后交服務器后臺處理。
ISAPI 應用的 DLL 不僅可以象 CGI 程序一樣被用戶請求激活,還可以被系統預先激活來監視用戶輸入;對于被用戶激活的 DLL ,在處理完一個用戶請求后不會馬上消失,而是繼續駐留在內存中等待處理別的用戶輸入,直到過了一段時間后一直沒有用戶輸入。一個 ISAPI 的 DLL ,可以在被用戶請求激活后長駐內存,等待用戶的另一個請求,還可以在一個 DLL 里設置多個用戶請求處理函數,此外, ISAPI 的 DLL 應用程序和 WWW 服務器處于同一個進程中,效率要顯著高于 CGI 。
每個使用 DLL 的請求都會賦給同一個處理器空間的線程, IIS 通常只是在初始化的時候為線程分好一個 線程池 后,在運轉周期里就一直使用這些線程。 線程池技術 減小了創建線程開銷。
ISAPI 出現在 CGI 之后,是一種優于 CGI 的動態網頁開發技術, ASP 是一個更好的 ISAPI ,而 ASP.NET 是更好的 ASP 。
ISAPI Classes
ISAPI describes an interface for Internet servers. An example of an ISAPI server is Windows NT Server running Microsoft Internet Information Server (IIS).
HTTP filters handle server requests. They can be used to handle the following types of applications:
( 1 ) Custom authentication schemes
( 2 ) Data compression
( 3 ) Encryption
( 4 ) Logging
Filter Classes
CHttpFilter
Filters selected HTTP requests sent to an ISAPI server.
CHttpFilterContext
Manages the context for an HTTP filter. This is a helper class to handle multiple, concurrent requests of a CHttpFilter object.
Server Classes
ISAPI server extensions process server requests. MFC ISAPI classes will not process requests from a Common Gateway Interface (CGI).
CHttpServer
Extends the functionality of an ISAPI server by processing client requests.
CHttpServerContext
Manages the context for an ISAPI server extension. This is a helper class to handle multiple, concurrent requests of a CHttpServer object.
Related Classes
CHtmlStream (流 IO 、動態內存管理)
Handles caching HTML output. Functionally similar to CMemFile .
源碼參考: <AFXISAPI.H> 、 <AFXISAPI.INL> 、 <ISAPIMIX.CPP> 、 <ISAPI.CPP>
// AFXISAPI.H
#include <VC98//Include// HTTPEXT.H >
#include <VC98//Include// HTTPFILT.H >
/////////////////////////////////////////////////////////////////
// AFXIASPI - MFC Internet Server API support
// CHtmlStream -- manages in-memory HTML
// Status codes for HTTP transactions
// Parse Map macros
參考:
《 MFC 深入淺出》李久進
第十四章《 SOCKET 類的設計和實現》
《 Visual C++ 6.0 網絡編程技術》 雷斌等
《 Visual C++ 6 From The Ground Up 》 John Paul Mueller
第三部分《 Visual C++ 與 Internet 》
《 ISAPI 實用技術指南》 K.Clements
《用 C++ 開發 Web 商用程序》
《 幾種網絡編程方式的比較 》
《 網絡編程學習小結 》
《 IIS 的 ISAPI 接口簡介 》
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
