wininet異步InternetReadFile和超時相關問題


wininet是對socket的封裝

主要流程為創建,連接,發送,接收,關閉幾個過程

所以在回調函數InternetStatusCallback中可以檢測到dwInternetStatus

#define INTERNET_STATUS_HANDLE_CREATED          60

#define INTERNET_STATUS_CONNECTING_TO_SERVER    20
#define INTERNET_STATUS_CONNECTED_TO_SERVER     21

#define INTERNET_STATUS_SENDING_REQUEST         30
#define INTERNET_STATUS_REQUEST_SENT            31


#define INTERNET_STATUS_RECEIVING_RESPONSE      40
#define INTERNET_STATUS_RESPONSE_RECEIVED       41

#define INTERNET_STATUS_REQUEST_COMPLETE        100


#define INTERNET_STATUS_CLOSING_CONNECTION      50
#define INTERNET_STATUS_CONNECTION_CLOSED       51

所以有的時候在設置超時時候不好用 因為只是設置了一個過程的超時整體超時還是不好用

如超時有

#define INTERNET_OPTION_CONNECT_TIMEOUT         2

#define INTERNET_OPTION_CONTROL_SEND_TIMEOUT    INTERNET_OPTION_SEND_TIMEOUT
#define INTERNET_OPTION_CONTROL_RECEIVE_TIMEOUT INTERNET_OPTION_RECEIVE_TIMEOUT
#define INTERNET_OPTION_DATA_SEND_TIMEOUT       7
#define INTERNET_OPTION_DATA_RECEIVE_TIMEOUT    8

應該設置各個流程的超時如:

InternetSetOption(NULL, INTERNET_OPTION_CONTROL_RECEIVE_TIMEOUT, &dwTimeout, sizeof(DWORD));

但是每個流程超時設置后應答時間和預期還是不一樣。可能有幾種原因,

1.各個流程不是按照最長流程超時返回,所以有的流程沒有花費timeout超時已經返回

2.設置超時還不夠完整 還有別的流程需要設置超時

3.設置超時失效http://support.microsoft.com/kb/176420也許是微軟BUG

 

關於異步wininet網上都說要用InternetReadFileEx而不用InternetReadFile但是我試了一下兩個函數其實一樣只是參數不一樣罷了
其實在使用該兩個函數的時候經常會返回 重疊 I/O 操作在進行中的錯誤,是http緩沖區正在讀數據。
 
當沒調用一次InternetReadFile 就會發現回調函數發送一次INTERNET_STATUS_RECEIVING_RESPONSE  接收數據的信號
首先在InternetReadFile要取得讀取的數據大小用 ret = HttpQueryInfo(hRequest, HTTP_QUERY_CONTENT_LENGTH,  szContentLength, &length,&index); HTTP_QUERY_CONTENT_LENGTH為數據大小。
主要在收到回調的兩個地方來調用InternetReadFile 一是 INTERNET_STATUS_REQUEST_COMPLETE 當數據量比較小的時候只需要讀一次就可以返回
所有數據 但數據量比較大的時候需要等INTERNET_STATUS_RESPONSE_RECEIVED  通知,不論數據量多大只需要這兩個過程足夠,而不是想象的可以有多次
INTERNET_STATUS_RESPONSE_RECEIVED 
一個完整小數據量流程為:
#define INTERNET_STATUS_HANDLE_CREATED          60
#define INTERNET_STATUS_CONNECTING_TO_SERVER    20
#define INTERNET_STATUS_CONNECTED_TO_SERVER     21
#define INTERNET_STATUS_SENDING_REQUEST         30
#define INTERNET_STATUS_REQUEST_SENT            31
#define INTERNET_STATUS_RECEIVING_RESPONSE      40
#define INTERNET_STATUS_RESPONSE_RECEIVED       41
#define INTERNET_STATUS_REQUEST_COMPLETE        100
一個完整大數據量流程為:
#define INTERNET_STATUS_HANDLE_CREATED          60
#define INTERNET_STATUS_CONNECTING_TO_SERVER    20
#define INTERNET_STATUS_CONNECTED_TO_SERVER     21
#define INTERNET_STATUS_SENDING_REQUEST         30
#define INTERNET_STATUS_REQUEST_SENT            31
#define INTERNET_STATUS_RECEIVING_RESPONSE      40
#define INTERNET_STATUS_RESPONSE_RECEIVED       41
#define INTERNET_STATUS_REQUEST_COMPLETE        100
#define INTERNET_STATUS_RECEIVING_RESPONSE      40
#define INTERNET_STATUS_RESPONSE_RECEIVED       41
但大數據量比較大的時候就會出現一個問題:
分兩個InternetReadFile怎么把HTTP_QUERY_CONTENT_LENGTH分成兩塊呢?
我試了多種方法:
1。InternetQueryDataAvailable(hRequest,&length,0,0);
取得可用數據長度但是失敗了。
2.通過回調函數中的lpvStatusInformation取得數據還是不對
 
通過調用InternetReadFile會發現雖然返回值是錯誤(重疊 I/O 操作在進行中的錯誤)但是數據buffer中時有數據的也就是說已經讀了一部分
最后經過調查和嘗試發現前兩種情況返回的長度不是讀取的數據的長度而是取得字符串的長度,為查找'\0'結束符返回的長度。最后經過嘗試發現
在第一次InternetReadFile把申請的HTTP_QUERY_CONTENT_LENGTH數據全部傳入
在第二次InternetReadFile傳入buffer+strlen(buffer1)驚奇的發現好用了。。。。
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM