Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

WinInet: асинхронные вызовы

14K
22 января 2007 года
Ёж_туманный
17 / / 16.06.2006
Цель: отправить асинхронный POST-зарпос, получить ответ.
Проблем 2 штуки:
1. Сообщение INTERNET_STATUS_REQUEST_COMPLETE приходит на каждый пакет данных (хотя должно приходить один раз после их получения, MSDN (c)), причём возвращаемые параметры:
 
Код:
INTERNET_ASYNC_RESULT* result = (INTERNET_ASYNC_RESULT*)lpvStatusInformation;

INTERNET_STATUS_REQUEST_COMPLETE: hInternet = 0x00cc000c, result->dwResult = 0x00000001,result->dwError = 0x00000000
INTERNET_STATUS_REQUEST_COMPLETE: hInternet = 0x00cc000c, result->dwResult = 0x00000001,result->dwError = 0x00000949

т.е. result->dwResult содержит не хендлер, а неизвестно что :( (если посылать запрос с помощью InternetOpenUrl, то в result->dwResult действительно хендлер, но нужен POST-запрос, InternetOpenUrl не подходит)
2. Иногда считывается только "хвост" ответа - видимо, только последний пакет.

Отправка запроса:
Код:
internetOpenHandle = ::InternetOpen( RequestHeaderUserAgent,
        INTERNET_OPEN_TYPE_PRECONFIG, 0, 0, INTERNET_FLAG_ASYNC );
    CUnicodeString requestString = buildRequest(); // Параметры запроса

    hConnect = InternetConnect( internetOpenHandle, hostName,
        hostPort, 0, 0, INTERNET_SERVICE_HTTP, 0, 0 );

    hHttpRequest = HttpOpenRequest( hConnect, L"POST", urlPath,
        0, 0, 0,
        INTERNET_FLAG_KEEP_CONNECTION | INTERNET_FLAG_NO_CACHE_WRITE | INTERNET_FLAG_NO_COOKIES |
        INTERNET_FLAG_NO_UI | INTERNET_FLAG_PRAGMA_NOCACHE | INTERNET_FLAG_RELOAD,
        (DWORD_PTR)this );

    if( hHttpRequest != 0 ) {
        // callback от WinInet
        assertLastError( ::InternetSetStatusCallback( hHttpRequest, InternetStatusCallback )
            != INTERNET_INVALID_STATUS_CALLBACK );

        // Отправляем запрос
        if( !::HttpSendRequest( hHttpRequest, 0, 0,
            (void*)requestString.Ptr(), requestString.Length()*sizeof(wchar_t) ) ) {
            // ошибка ERROR_IO_PENDING означает "в процессе дозвона до сервера"
            // (нормальное состояние)
            if( GetLastError() != ERROR_IO_PENDING ) {
                int err = GetLastError();
                ::InternetCloseHandle( hHttpRequest );
                ::InternetCloseHandle( hConnect );
                SetLastError( err );
                assertLastError( false );
            }
        }
    } else {
        ::InternetCloseHandle( hConnect );
        assert( false );
    }


Читает сообщение код (взято из примера от MS):
Код:
CString page;

        DWORD bytesRead;
        static const int maxAttempts = 100;
        do {
            // Ждём данные
            DWORD available;
            int attempts = 0; // количество попыток перебороть ERROR_IO_PENDING
            while( !::InternetQueryDataAvailable( responseHandle, &available, 0, 0 ) ) {
                if( GetLastError() != ERROR_IO_PENDING || attempts > maxAttempts) {
                    assertLastError( false );
                }
                attempts++;
                Sleep( 1 );
            }
            // Получили данные, считываем
            CString buffer;
            char *bf = buffer.GetBuffer( available + 1 );
            while( !::InternetReadFile( responseHandle, bf, available, &bytesRead ) ) {
                if( GetLastError() != ERROR_IO_PENDING || attempts > maxAttempts ) {
                    assertLastError( false );
                }
                attempts++;
                Sleep( 1 ); // min пауза
            }
            // Сохраняем полученные данные
            buffer.ReleaseBuffer( bytesRead );
            page += buffer;
        } while( bytesRead > 0 );

        closeWinInetHandles();
14K
24 января 2007 года
Ёж_туманный
17 / / 16.06.2006
с приходом тучи Request_Complete сообщений разобрался - они приходят, если InternetQueryDataAvalible не может сразу вернуть число и приходится некоторое время ждать подгрузки данных, а вот с потерей начала пакета разобраться пока не получилось :(

кто-нибудь искользовал WinInet в асинхронном режиме?
Как посылать сообщения? HttpSendRequest vs HttpSendRequestEx? Асинхронность упоминается только относительно второй, но работает (похоже) и первая... или я не прав и не стоит её использовать? Тогда как искользовать HttpSendRequestEx??
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог