Windows Mobile下异步使用WinInet库下载数据

来源:互联网 发布:android 书籍 知乎 编辑:程序博客网 时间:2024/06/05 19:00

现在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函数。

原创粉丝点击