現在windows mobile系統雖然開始漸漸淡出人們的視線,我現在也轉到android上了,可是做了這麼些年windows mobile開發總覺得要留下點什麼,是以開始寫點這方面的部落格留個紀念,其實是把以前的東西重新整理回顧一下。
使用WinInet庫進行網絡下載下傳時,通常使用InternetReadFile函數,但它是同步下載下傳,是以當正在下載下傳時網絡突然斷線,程式有可能會卡在這個函數當中,當然也可以設定一個逾時來控制。當程式必須退出時,使用同步方式的話則必須等待函數完成或逾時,而用異步方式則可以友善的控制。
1、介紹程式下載下傳的流程
//打開Internet,,标記使用異步方式,設定标志位INTERNET_FLAG_ASYNC
m_hSession = ::InternetOpen(AGENTNAME,INTERNET_OPEN_TYPE_DIRECT, NULL, NULL,INTERNET_FLAG_ASYNC);
//設定回調函數AsyncInternetCallback,函數傳回舊的回調函數
INTERNET_STATUS_CALLBACK pOldCallback = InternetSetStatusCallback(m_hSession, AsyncInternetCallback);
//打開一個url位址,最後一個參數系統會傳遞給回調函數
m_hInternetFile = ::InternetOpenUrl(m_hSession, lpszUrl, NULL, NULL, INTERNET_FLAG_RELOAD,(DWORD)this);
//傳回值為NULL,并且得到的錯誤是ERROR_IO_PENDING,則等待,可以從回調函數處得到打//開的句柄值
if(m_hInternetFile == NULL)
{
if(GetLastError() == ERROR_IO_PENDING)
{
//等待在回調函數中取得打開的句柄
}
else
{
//出錯
}
}
//開始下載下傳,以下取得資料的代碼可以放在一個循環中,直到取得全部的資料
pBuffer = new BYTE[dwBufferSize];
memset(pBuffer,0,dwBufferSize);
INTERNET_BUFFERS i_buf = {0};
i_buf.dwStructSize = sizeof(i_buf);
i_buf.lpvBuffer = pBuffer;
i_buf.dwBufferLength = dwBufferSize;
//重置讀資料事件
ResetEvent(m_hEventComplete);
BOOL bRead = ::InternetReadFileExA(m_hInternetFile,(LPINTERNET_BUFFERSA)&i_buf,IRF_ASYNC,(DWORD)this)
//傳回值為FALSE,并且錯誤号為ERROR_IO_PENDING,則說明正在異步取得資料;有時候網絡比較暢通時會傳回TRUE,這時候資料已經取得
if ( !bRead )
{
DWORD dwError = GetLastError();
if (ERROR_IO_PENDING == dwError)
{
//等待讀取資料的事件被激活
}
else
//出錯
}
else
資料已經取得
2、介紹回調函數
void AsyncInternetCallback(HINTERNET hInternet,DWORD dwInternetStatus, LPVOID lpvStatusInformation, DWORD dwStatusInformationLength)
{
switch(dwInternetStatus)
{
//句柄被建立
case INTERNET_STATUS_HANDLE_CREATED:
m_hInternetFile = (HINTERNET)(((LPINTERNET_ASYNC_RESULT)(lpvStatusInformation))->dwResult);
break;
//句柄被關閉
case INTERNET_STATUS_HANDLE_CLOSING:
case INTERNET_STATUS_CONNECTION_CLOSED:
break;
//一個請求完成,比如一次句柄建立的請求,或者一次讀資料的請求,在這裡激活相應的事件
case INTERNET_STATUS_REQUEST_COMPLETE:
if (ERROR_SUCCESS == ((LPINTERNET_ASYNC_RESULT)(lpvStatusInformation))->dwError)
{
//激活等待的事件
}
else
{
//激活出錯的事件
}
break;
}
}
注意:調用::InternetReadFileEx有一個需要注意的地方:在Unicode環境下(比如WinCE中),系統會自動轉譯調用InternetReadFileExW函數,這個函數會直接傳回錯誤号120,這時候要使用異步操作必須調用InternetReadFileExA函數。