先使用 FtpFindFirstFile, GopherFindFirstFile, 或 InternetOpenUrl ,然后將其返回的句柄作為參數 傳遞給 InternetFindNextFile 進行繼續查找,持續調用 InternetFindNextFile 知道返回擴展的錯誤信息 ERROR_NO_MORE_FILES 來完成整個搜索,調用 GetLastError 來獲取最后的錯誤信息.
6.HTTP 會話
使用 WinINet 函數訪問WWW資源
(1)初始化 WWW 連接
將服務類型設為 INTERNET_SERVICE_HTTP 調用 InternetConnect 來建立一個 HTTP 會話
HINTERNET InternetConnect(
__in HINTERNET hInternet, //InternetOpen 返回的句柄
__in LPCTSTR lpszServerName, //可以描述目標服務器的字符串
__in INTERNET_PORT nServerPort,//目標服務器的端口
__in LPCTSTR lpszUsername,//用戶名
__in LPCTSTR lpszPassword,//密碼
__in DWORD dwService,//使用的服務類型
__in DWORD dwFlags,
__in DWORD_PTR dwContext
);
nServerPort
Value |
Meaning |
INTERNET_DEFAULT_FTP_PORT
|
Uses the default port for FTP servers (port 21).
|
INTERNET_DEFAULT_GOPHER_PORT
|
Uses the default port for Gopher servers (port 70).
|
INTERNET_DEFAULT_HTTP_PORT
|
Uses the default port for HTTP servers (port 80).
|
INTERNET_DEFAULT_HTTPS_PORT
|
Uses the default port for Secure Hypertext Transfer Protocol (HTTPS) servers (port 443).
|
INTERNET_DEFAULT_SOCKS_PORT
|
Uses the default port for SOCKS firewall servers (port 1080).
|
INTERNET_INVALID_PORT_NUMBER
|
Uses the default port for the service specified by dwService.
|
ldwService
Value |
Meaning |
INTERNET_SERVICE_FTP
|
FTP service.
|
INTERNET_SERVICE_GOPHER
|
Gopher service.
|
INTERNET_SERVICE_HTTP
|
HTTP service.
|
(2)建立請求
調用 HttpOpenRequest 來建立一個 HTTP 請求,不過這個函數不會自動把請求發送出去,要發送請求需要調用 HttpSendRequest
HttpOpenRequest 原型
HINTERNET HttpOpenRequest(
__in HINTERNET hConnect, // InternetConnect 函數返回的句柄
__in LPCTSTR lpszVerb, // 動作,有GET, PUT, POST。也可以設置為 NULL ,會被當成默認的 GET 來用
__in LPCTSTR lpszObjectName, // 一個描述你請求資源的字符串,當請求一個默認頁面時令這個參數指向一個空串
__in LPCTSTR lpszVersion, // HTTP 版本,這個參數為 NULL 時,默認使用""HTTP/1.1""
__in LPCTSTR lpszReferer, // 說明了lpszObjectName是取自哪個文件,可以設為NULL
__in LPCTSTR *lplpszAcceptTypes, //
是一個指向LPCTSTR數組的指針!數組以一個NULL指針結束。指定了程序接受的內容的類型,設為空則不接受 任何類型的內容,設為空串則等價于""text/*"",即不接受文本文件以外的圖片等文件,只接受某種特定的文件可以用類似"image/gif, image/jpeg"的方式。關于更多內容類型 請看這里
__in DWORD dwFlags, // 一般都可以設置為 0
__in DWORD_PTR dwContext // 一般都可以設置為 0
);
(3)添加請求
HttpAddRequestHeaders 原型
BOOL HttpAddRequestHeaders(
__in HINTERNET hConnect,//HttpOpenRequest 返回的句柄
__in LPCTSTR lpszHeaders,//包含要添加到請求中的頭的字符串的指針,每個頭都要以一個 CR/LF ( "r"n"r"n ) 對結束
__in DWORD dwHeadersLength,//lpszHeaders指向的字符串的長度(以TCHAR類型記). 如果這個參數被設為-1,則字符串被當作以0結尾的字符串處理,自動計算該字符串的長度
__in DWORD dwModifiers
);
dwModifiers
可以是下面這些值的組合
Value |
Meaning |
HTTP_ADDREQ_FLAG_ADD
|
Adds the header if it does not exist. Used with HTTP_ADDREQ_FLAG_REPLACE.
|
HTTP_ADDREQ_FLAG_ADD_IF_NEW
|
Adds the header only if it does not already exist; otherwise, an error is returned.
|
HTTP_ADDREQ_FLAG_COALESCE
|
Coalesces headers of the same name.
|
HTTP_ADDREQ_FLAG_COALESCE_WITH_COMMA
|
Coalesces headers of the same name. For example, adding
"Accept: text/*" followed by "Accept: audio/*" with this flag results in
the formation of the single header "Accept: text/*, audio/*". This
causes the first header found to be coalesced. It is up to the calling
application to ensure a cohesive scheme with respect to
coalesced/separate headers.
|
HTTP_ADDREQ_FLAG_COALESCE_WITH_SEMICOLON
|
Coalesces headers of the same name using a semicolon.
|
HTTP_ADDREQ_FLAG_REPLACE
|
Replaces or removes a header. If the header value is
empty and the header is found, it is removed. If not empty, the header
value is replaced.
|
(4)發送一個請求
HttpSendRequest
BOOL HttpSendRequest(
__in HINTERNET hRequest, //HttpOpenRequst 返回的句柄
__in LPCTSTR lpszHeaders, //附加到請求上的頭,可以為NULL
__in DWORD dwHeadersLength, //lpszHeaders指向的字符串的長度(以TCHAR類型記).
如果這個參數被設為-1,當調用的是HttpSendRequestA時則字符串被當作以0結尾的字符串處理,自動計算該字符串的長度。當調用的是
HttpSendRequestW時就會產生一個錯誤
__in LPVOID lpOptional, //當使用POST或PUT方法時,這個參數指向的數據會緊接著請求被發送出去。沒有需要發送的數據則可以設置為NULL
__in DWORD dwOptionalLength //lpOptional數據的字節長度,無數據時設置為0
);
(5)向服務器發送數據
方法一:參見上面HttpSentRequest的lpOptional參數的說明
方法二:使用 InternetWriteFile 向一個句柄里發送數據,然后使用 HttpSendRequestEx 發送
(6)查詢一個請求的信息
HttpQueryInfo
BOOL HttpQueryInfo(
__in HINTERNET hRequest, /*由 HttpOpenRequest 或 InternetOpenUrl 返回的句柄*/
__in DWORD dwInfoLevel,/* Query Info Flags.
*/
__inout LPVOID lpvBuffer, /*用于存儲查詢結果的緩沖區,不可為NULL*/
__inout LPDWORD lpdwBufferLength,/*lpvBuffer指向的緩沖區的字節長度
若函數執行成功,這個變量存儲的是寫到緩沖區里的數據長度。如果數據是字符串則返回的長度不包括字符串的結束字符
如果函數發生 ERROR_INSUFFICIENT_BUFFER 錯誤, 則這個變量里保存的是數據的實際字節長度程序需要根據這個長度重新分配內存,再執行一次這個函數*/
__inout LPDWORD lpdwIndex /*沒看大明白,不過似乎可以設置為NULL
Pointer to a zero-based header index used to enumerate multiple headers with the same name.
When calling the function, this parameter is the index of the specified header to return.
When the function returns, this parameter is the index of the next header.
If the next index cannot be found, ERROR_HTTP_HEADER_NOT_FOUND is returned.*/
);
(7)從 WWW 上下載資源
在調用 HttpOpenRequest 和 HttpSendRequest 之后, 程序可以使用 InternetReadFile, InternetQueryDataAvailable, InternetSetFilePointer 來下載HTTP服務器上的資源了。
BOOL InternetQueryDataAvailable(//查詢數據的長度
__in HINTERNET hFile, //由 InternetOpenUrl, FtpOpenFile, GopherOpenFile, 或 HttpOpenRequest
返回的句柄
__out LPDWORD lpdwNumberOfBytesAvailable, //用于存放數據長度的指針
__in DWORD dwFlags, //保留參數,置0
__in DWORD_PTR dwContext //保留參數,置0
);
BOOL InternetReadFile( //讀取句柄的數據
__in HINTERNET hFile, // InternetOpenUrl, FtpOpenFile, GopherOpenFile, HttpOpenRequest 創建的句柄
__out LPVOID lpBuffer, // 存放數據的緩沖區
__in DWORD dwNumberOfBytesToRead, // 準備讀取的字節數
__out LPDWORD lpdwNumberOfBytesRead // 讀取了的字節數
);
DWORD InternetSetFilePointer(
//設置InternetReadFile的文件位置(莫非多線程下載就是用這個實現的?),服務器不支持隨機訪問的話函數調用會失敗,如果
InternetReadFile已經讀取到了文件的末尾,這個函數的調用也會失敗。
__in HINTERNET hFile, //由 InternetOpenUrl (on an HTTP or HTTPS URL)創建。
或由HttpOpenRequest 創建(使用 GET 或 HEAD方法,而且句柄已經被 HttpSendRequest 訪問過了).
這個句柄也不可以使用 INTERNET_FLAG_DONT_CACHE 或 INTERNET_FLAG_NO_CACHE_WRITE 標志
__in LONG lDistanceToMove, //移動的字節數。正數向后移動,負數向前移動
__in PVOID pReserved, //保留參數,為NULL
__in DWORD dwMoveMethod, //指定了移動指針時的參考點。FILE_BEGIN(使用這個標志時,移動的字節數被當作無符號數處理)、FILE_CURRENT、FILE_END(如果內容的長度無法獲得,則使用這個標志時會失敗)
__in DWORD_PTR dwContext //保留參數,為NULL
);