2013-06-20 2 views
0

Я пытаюсь написать приложение Asyncronous Wininet. Я прочитал данные в моей функции обратного вызова в случае INTERNET_STATUS_REQUEST_COMPLETE, и я также обрабатываю ошибки ERROR_IO_PENDING. Но после некоторых данных, прочитанных из Интернета, функция InternetReadFileEx дает мне 10035 = WSAEWOULDBLOCK (немедленная незавершенная операция сокета не может быть завершена). После этой ошибки я снова вызываю InternetReadFileEx, и на этот раз он дает мне 1008 = ERROR_NO_TOKEN (попытка была сделана для ссылки на токен, который не существует.). Я думаю, что мой дизайн неправильный, и я получаю эту ошибку из-за этого.InternetReadFileEx дает 10035 и 1008 ошибок

Вот отрывок из моего кода:

case INTERNET_STATUS_REQUEST_COMPLETE: 
    { 
     BOOL bAllDone= FALSE; 
     DWORD lastError; 

     do 
     { 
      //Create INTERNET_BUFFERS 
      char m_pbReadBuffer[4096]; 
      INTERNET_BUFFERS BuffersIn; 
      ZeroMemory(&BuffersIn, sizeof(INTERNET_BUFFERS)); 
      BuffersIn.dwStructSize = sizeof(INTERNET_BUFFERS); 
      BuffersIn.lpvBuffer = m_pbReadBuffer; 
      BuffersIn.dwBufferLength = 4096; 

      InternetReadFileEx(ReqContext->File, &BuffersIn, IRF_ASYNC, 1); 

      //HERE I GOT THOSE 10035 and 1008 ERRORS 
      lastError = GetLastError(); 

      if(lastError == 997) // handling ERROR_IO_PENDING 
       break;//break the while loop 

      //append it to my ISTREAM 
      (ReqContext->savedStream)->Write(BuffersIn.lpvBuffer, BuffersIn.dwBufferLength, NULL); 

      if (BuffersIn.dwBufferLength == 0) 
       bAllDone = TRUE; 

    }while(bAllDone == FALSE); 

       //delete[] m_pbReadBuffer; 

    if(bAllDone == TRUE && lastError== 0) 
    { 
     //these are for passing the ISTREAM to the function which calls "InternetOpenUrl" 
     LARGE_INTEGER loc; 
     loc.HighPart = 0; 
     loc.LowPart = 0; 
     ReqContext->savedStream->Seek(loc, STREAM_SEEK_SET, NULL); 
     ReqContext->savedCallback->OnUrlDownloaded(S_OK, ReqContext->savedStream); //Tell silverlight ISTREAM is ready 
     ReqContext->savedStream->Release(); 
     ReqContext->savedCallback->Release(); 

     InternetCloseHandle(ReqContext->File); 
     InternetSetStatusCallback(ReqContext->Connection, NULL); 
     InternetCloseHandle(ReqContext->Connection); 
     delete[] ReqContext; 
     } 
    } 
    break; 

Может кто-нибудь дать мне руку, чтобы исправить это? Спасибо всем, кто помог ...

ответ

1

GetLastError() имеет смысл только в том случае, если InternetReadFileEx() (или любой другой API, если на то пошло) фактически не с ошибкой. В противном случае вы будете обрабатывать ошибку из более раннего вызова API, предоставляя вашему коду ложную иллюзию, что ошибка произошла, когда она действительно может отсутствовать. Вы ДОЛЖНЫ обращать внимание на возвращаемые значения API, но в настоящее время вы игнорируете возвращаемое значение InternetReadFileEx().

Хуже того, вы используете InternetReadFileEx() в режиме async, но используете буфер приема, который является локальным для обработчика обратного вызова INTERNET_STATUS_REQUEST_COMPLETE. Если InternetReadFileEx() сбой с ошибкой ERROR_IO_PENDING, чтение выполняется в фоновом режиме, и INTERNET_STATUS_REQUEST_COMPLETE будет запущен, когда чтение будет завершено. Однако, когда эта ошибка возникает, вы нарушаете свой цикл (хотя чтение все еще продолжается), и этот буфер выйдет за пределы области до того, как будет завершено чтение. Пока чтение все еще продолжается, буфер приема по-прежнему находится в стеке, и InternetReadFileEx() все еще пишет ему, но он может повторно использоваться для других вещей одновременно, потому что ваш код перешел к другим вещам и не сделал дождитесь окончания чтения.

Вам нужно пересмотреть свой подход. Либо:

  1. IRF_ASYNC удалить флаг, так что, как остальная часть вашего кода обратного вызова ожидает InternetReadFileEx() на себя.

  2. перезапишите код для правильной работы в асинхронном режиме. Динамически распределите буфер приема (или, по крайней мере, сохраните его в другом месте, который остается в области во время чтения async), не вызывайте IStream::Write(), если у вас на самом деле нет данных для записи (только когда InternetReadFileEx() вернул TRUE сразу, или вы получите событие INTERNET_STATUS_REQUEST_COMPLETE с кодом успеха от более ранней InternetReadFileEx()/ERROR_IO_PENDING вызова) и т.д.

Есть много онлайн примеров и учебных пособий, которые показывают, как использовать InternetReadFileEx() в асинхронном режиме. Поиск вокруг.

+0

Благодарим вас за советы. Я решил свою проблему. –