【问题标题】:WinHttpSendRequest fails with ERROR_WINHTTP_SECURE_FAILUREWinHttpSendRequest 失败并显示 ERROR_WINHTTP_SECURE_FAILURE
【发布时间】:2017-11-29 13:49:53
【问题描述】:

以编程方式与网络通信不是我的专业领域,但我设法通过从网上找到的示例中剪切和粘贴代码来创建一个 read_web_page() 函数,并且该代码已经运行了好几个月,每天都没有错误。

碰巧我在工作中的主要 Windows-10 PC 发生故障,在等待维修时,我现在不得不在家中的 Windows-7 PC 上运行(相同的)代码。

但是现在我出现了一个我以前从未见过的错误。我调用以下代码(简化):

    // code to handle bad return values from the following three functions ommitted...

    HINTERNET hsession = WinHttpOpen(0,WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME,WINHTTP_NO_PROXY_BYPASS, 0);

    HINTERNET hconnect = WinHttpConnect(hsession, (LPCWSTR)thewebsite, INTERNET_DEFAULT_HTTPS_PORT , 0);

    HINTERNET hrequest = WinHttpOpenRequest(hconnect, L"GET", (LPCWSTR)thesubdirectory, NULL, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, WINHTTP_FLAG_SECURE);

    if (!WinHttpSendRequest(hrequest, WINHTTP_NO_ADDITIONAL_HEADERS, 0, WINHTTP_NO_REQUEST_DATA, 0, 0, 0))
    {
        int err = GetLastError();

通常 WinHttpSendRequest 返回零,但现在返回非零值,GetLastError() 返回值 12175(等于 ERROR_WINHTTP_SECURE_FAILURE)。

我连接的 (https) URL 一直是相同的,当我在浏览器中输入它时,网站仍然正常显示。

也许PC和位置的整个变化是巧合,问题是由我正在阅读的网站的内部变化引起的(它不在我的控制之下)......但我不知道如何开始诊断(或修复)故障。可能与我的 ISP 有关吗?

documentation for WinHttpSendRequest 表示可以通过设置回调函数找到有关此错误的更详细信息,但描述如何完成的文档对我来说是不可理解的,我在任何地方都找不到任何示例代码。

编辑:为了解决 Barmak 对网站和子目录的担忧,创建它们的代码如下:

char *char_thewebsite = "www.thewebsite.com";
char *char_thesubdirectory = "sub";

int n_website = MultiByteToWideChar(CP_ACP, 0, char_thewebsite, -1, NULL, 0);
int n_subdir = MultiByteToWideChar(CP_ACP, 0, char_thesubdirectory, -1, NULL, 0);

thewebsite = new WCHAR[n_website];
thesubdirectory = new WCHAR[n_subdir];

MultiByteToWideChar(CP_ACP, 0, char_thewebsite, -1, (LPWSTR)thewebsite, n_website);
MultiByteToWideChar(CP_ACP, 0, char_thesubdirectory, -1, (LPWSTR)thesubdirectory, n_subdir);

【问题讨论】:

  • (LPCWSTR)thewebsite 这个演员阵容很可疑。 thewebsitethesubdirectory 的声明是什么?是char 还是std::string 等?
  • 该错误表示该网站不支持安全连接。目标网站是否失去了安全连接?尝试使用INTERNET_DEFAULT_HTTP_PORT 访问该站点并将WINHTTP_FLAG_SECURE 替换为零。顺便说一句,如果你只是想阅读一个网站,WinINet 会容易得多。
  • @Barmack:如果我这样做了,那么稍后当我调用 WinHttpReceiveResponse(hrequest, NULL) 它返回一个非零值并且 getlasterror 再次为 12175。
  • 我认为您使用了错误的标志。您如何通过网络浏览器访问该网站? "http://www.thewebsite.com""https://www.thewebsite.com"
  • 后者——“https”

标签: c winapi


【解决方案1】:

这是一个长评论,不是答案!

WinINet 更简单,如果您不需要 WinHTTP 服务器功能,可以使用 WinINet 库。但是你不能同时使用 WinINet 和 WinHTTP。

声明字符串时,最好以 UTF-16 字符串 wchar_t *str = L"str" 开头。有时您的源字符串是 UTF-8,在这种情况下,您可以使用 MultiByteToWideChar(CP_UTF8...) 转换为 UTF-16。

WinINet 示例:

#include <iostream>
#include <fstream>
#include <Windows.h>
#include <WinINet.h>

#pragma comment(lib, "WinINet.lib")

int main()
{
    const wchar_t* url = L"https://stackoverflow.com/questions";
    std::ofstream fout(L"c:\\test\\test.htm");
    HINTERNET hopen = InternetOpen(L"MyAppName",
        INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
    if(hopen)
    {
        DWORD flags = INTERNET_FLAG_DONT_CACHE;
        if(wcsstr(url, L"https://") == url)
            flags |= INTERNET_FLAG_SECURE;
        HINTERNET hinternet = InternetOpenUrl(hopen, url, NULL, 0, flags, 0);
        if(hinternet)
        {
            char buf[1024];
            DWORD received = 0;
            while(InternetReadFile(hinternet, buf, sizeof(buf), &received))
            {
                if(!received) break;
                fout.write(buf, received);
            }
            std::cout << "success!\n";
            InternetCloseHandle(hinternet);
        }
        InternetCloseHandle(hopen);
    }
    return 0;
}

【讨论】:

  • 我必须做一些小调整才能让它编译——也许是因为我的字符集设置为“使用多字节字符集”……但无论如何,它现在可以正常工作了.顺便说一句,我认为你可以在同一个程序中同时使用 WinINet 和 WinHTTP,只要你不在同一个源文件中包含 Winhttp.h 和 WinINet.h。非常感谢您的帮助。
  • 我忘记了 WinHTTP 只是 Unicode,这解释了你所做的转换。 WinInet 函数有 ANSI 版本,可以接受char* 输入。
猜你喜欢
  • 1970-01-01
  • 2015-12-31
  • 1970-01-01
  • 2021-12-10
  • 2020-02-08
  • 2011-05-21
  • 2012-05-04
  • 2019-07-21
  • 1970-01-01
相关资源
最近更新 更多