Попытка получить сокет из Wininet HTTP-соединения - PullRequest
1 голос
/ 08 ноября 2011

У нас есть устаревшее приложение, которое реализует туннель SSL через веб-прокси. Он использует Wininet API и отлично работал в течение многих лет на XP, но теперь он не работает на Windows 7. Я попытался изолировать код и создал небольшую программу для воспроизведения проблемы. Это небольшая программа на C, скомпилированная с MSVC 9. См. Ниже.

В Windows 7 после подключения к прокси (код состояния 200) я просто не могу получить дескриптор сокета из API. Все, что я получаю, это INVALID_SOCKET, хотя все функции wininet возвращаются успешно, а GetLastError () возвращает 0.

На компьютере с XP все работает нормально, и возвращаемый сокет действителен.

У кого-нибудь есть идеи? Заранее большое спасибо.

#include <windows.h>
#include <wininet.h>
#include <stdio.h>

const char *_connect()
{
    HINTERNET hOpen = 0;
    HINTERNET hConnect = 0;
    HINTERNET hRequest = 0;
    int remotePort = 443;
    const char *remoteHost = "a.b.c.d"; // Cannot disclose
    hOpen = InternetOpen("wininet-test", INTERNET_OPEN_TYPE_PRECONFIG, 0, 0, 0);
    if (!hOpen) return "InternetOpen";
    hConnect = InternetConnect(hOpen, remoteHost, remotePort, 0, 0, INTERNET_SERVICE_HTTP, 0, 0);
    if (!hConnect) return "InternetConnect";
    {
        DWORD flags =
            INTERNET_FLAG_CACHE_IF_NET_FAIL |
            INTERNET_FLAG_IGNORE_CERT_CN_INVALID |
            INTERNET_FLAG_IGNORE_CERT_DATE_INVALID |
            INTERNET_FLAG_KEEP_CONNECTION |
            INTERNET_FLAG_NO_CACHE_WRITE |
            INTERNET_FLAG_PRAGMA_NOCACHE |
            INTERNET_FLAG_RELOAD |
            INTERNET_FLAG_RESYNCHRONIZE |
            INTERNET_FLAG_SECURE;
        char url[100];
        sprintf(url, "http://%s:%d/", remoteHost, remotePort);
        hRequest = HttpOpenRequest(hConnect, "GET", "connect.html", "HTTP/1.0", url, 0, flags, 0);
        if (!hRequest) return "HttpOpenRequest";
    }
    {
        DWORD flags=0;
        DWORD bufferLength = sizeof(flags);
        if (!InternetQueryOption(hRequest, INTERNET_OPTION_SECURITY_FLAGS, &flags, &bufferLength)) {
            return "InternetQueryOption";
        }
        flags |= (SECURITY_FLAG_IGNORE_UNKNOWN_CA | SECURITY_FLAG_IGNORE_REVOCATION);
        if (!InternetSetOption(hRequest, INTERNET_OPTION_SECURITY_FLAGS, &flags, sizeof(flags))) {
            return "InternetSetOption";
        }
    }
    if (!HttpSendRequest(hRequest, 0, 0, 0, 0)) {
        return "HttpSendRequest";
    } else {
        char buffer[4];
        DWORD bufferSize = sizeof(buffer);
        if (!HttpQueryInfo(hRequest, HTTP_QUERY_STATUS_CODE, &buffer, &bufferSize, NULL)) {
        return "HttpQueryInfo";
        } else if (atoi(buffer) != 200) {
            return "status code";
        }
    }
    {
        INTERNET_DIAGNOSTIC_SOCKET_INFO idsi;
        DWORD bufferSize = sizeof(idsi);
        if (!InternetQueryOption(hRequest, INTERNET_OPTION_DIAGNOSTIC_SOCKET_INFO, &idsi, &bufferSize)) {
            return "InternetQueryOption";
        } else if (idsi.Socket == INVALID_SOCKET) {
            /* This is always the case on our Windows 7 platform, why? */
            return "invalid socket";
        }
    }
    return 0;
}

int main(int argc, const char **argv)
{
    const char *error = _connect();
    if (error) {
        printf("ERROR: %s (%d)\n", error, GetLastError());
    } else {
        printf("SUCCESS\n");
    }
    return 0;
}

Ответы [ 3 ]

2 голосов
/ 09 ноября 2011

Использует ли HTTP-запрос keep-alives?Если нет, то я думаю, что WinInet под Win7 делает недействительным дескриптор сокета после его закрытия при получении ответа сервера, тогда как XP не делает сокет недействительным.

2 голосов
/ 26 августа 2012

Из MSDN

INTERNET_OPTION_DIAGNOSTIC_SOCKET_INFO 67

Извлекает структуру INTERNET_DIAGNOSTIC_SOCKET_INFO, которая содержит данные об указанном HTTP-запросе.Этот флаг используется InternetQueryOption.

Windows 7: эта опция больше не поддерживается.

0 голосов
/ 08 ноября 2011

Вы уверены, что ваш проект не компилируется для Unicode? В этом случае вам нужно изменить объявление char на wchar_t и добавить к своим константам L, например:

const wchar_t * pszTmp = L"hello world";
...