HttpSendRequestA 为假且 return 0
HttpSendRequestA is false and return 0
你好,我正在尝试使用 WinInet 和 costum 用户代理下载一些东西,问题是我在 HttpSendRequestA 失败,错误 return 是 0
我不知道这个错误是什么意思我已经尝试查找它但没有出现
我使用 std::to_string(GetLastError());
得到错误
下面是代码
std::string GetUrlData(const std::string& resource, const std::string& host)
{
std::string output = "";
output.clear();
HINTERNET hIntSession = InternetOpenA("token", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
if (!hIntSession) {
return "ERROR: Session Cannot Start";
}
HINTERNET hHttpSession = InternetConnectA(hIntSession, host.c_str(), 80, 0, 0, INTERNET_SERVICE_HTTP, 0, NULL);
if (!hHttpSession) {
InternetCloseHandle(hIntSession);
return "ERROR: Cannot Connect To Internet";
}
HINTERNET hHttpRequest = HttpOpenRequestA(hHttpSession, "GET", resource.c_str(), 0, 0, 0, INTERNET_FLAG_RELOAD, 0);
if (!hHttpRequest) {
InternetCloseHandle(hHttpSession);
InternetCloseHandle(hIntSession);
return "ERROR: Http Request Failed";
}
// const char* szHeaders = "User-Agent: Mozzila\r\n";
if (!HttpSendRequestA(hHttpRequest, NULL, 0, NULL, 0)) {
InternetCloseHandle(hHttpRequest);
InternetCloseHandle(hHttpSession);
InternetCloseHandle(hIntSession);
return "ERROR: Http Request Failed 2";
}
char szBuffer[1024];
DWORD dwRead = 0;
do {
if (!InternetReadFile(hHttpRequest, szBuffer, sizeof(szBuffer), &dwRead)) {
InternetCloseHandle(hHttpRequest);
InternetCloseHandle(hHttpSession);
InternetCloseHandle(hIntSession);
return "ERROR: Cannot Download";
}
if (dwRead == 0)
break;
output.append(szBuffer, dwRead);
}
while (true);
return output;
}
我这样称呼这个函数std::string
data = GetUrlData("http://example.com/", "http://example.com/");
问题是你的 host
参数应该只是主机名,而不是完整的 URL 并且资源应该只是主机上的资源部分。
像这样:
std::string data = GetUrlData("/", "example.com");
旁注:您获得了最多三个需要手动释放的资源,并尝试确保使用 InternetCloseHandle()
释放它们,但它很快就会变得冗长,您最终可能会忘记一个。碰巧的是,如果您的 GetUrlData()
调用成功,您不会释放 任何 资源。
考虑将每个资源包装在 std::unique_ptr
中以使其自动释放。它不仅使它更安全,还使代码更易于阅读和维护。
示例:
#include <Windows.h>
#include <wininet.h>
#include <iostream>
#include <memory>
#include <stdexcept>
#include <string>
#include <type_traits>
// custom deleter for the resource
struct internet_deleter {
void operator()(HINTERNET hi) { InternetCloseHandle(hi); }
};
// the resource's wrapper type
using ihandle = std::unique_ptr<std::remove_pointer_t<HINTERNET>, internet_deleter>;
// functions for acquiring resources
auto RAII_InternetOpen() {
ihandle rv(InternetOpenA("token", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0));
if (rv) return rv;
throw std::runtime_error("InternetOpenA: " + std::to_string(GetLastError()));
}
auto RAII_InternetConnect(const ihandle& hIntSession, const std::string& host) {
ihandle rv(
InternetConnectA(hIntSession.get(), host.c_str(), 80, 0, 0,
INTERNET_SERVICE_HTTP, 0, NULL));
if (rv) return rv;
throw std::runtime_error("InternetConnectA: " + std::to_string(GetLastError()));
}
auto RAII_HttpOpenRequest(const ihandle& hHttpSession, const std::string& resource) {
ihandle rv(
HttpOpenRequestA(hHttpSession.get(), "GET", resource.c_str(), 0, 0, 0,
INTERNET_FLAG_RELOAD, 0));
if (rv) return rv;
throw std::runtime_error("HttpOpenRequestA: " + std::to_string(GetLastError()));
}
加上以上三个函数,GetUrlData()
函数变得更简单,不会泄露资源:
std::string GetUrlData(const std::string& resource, const std::string& host)
{
std::string output;
auto hIntSession = RAII_InternetOpen();
auto hHttpSession = RAII_InternetConnect(hIntSession, host);
auto hHttpRequest = RAII_HttpOpenRequest(hHttpSession, resource);
if (!HttpSendRequestA(hHttpRequest.get(), NULL, 0, NULL, 0))
throw std::runtime_error("HttpSendRequestA: " +
std::to_string(GetLastError()));
char szBuffer[1024];
DWORD dwRead = 0;
do {
if (!InternetReadFile(hHttpRequest.get(), szBuffer, sizeof(szBuffer), &dwRead))
throw std::runtime_error("InternetReadFile: " +
std::to_string(GetLastError()));
if (dwRead == 0)
break;
output.append(szBuffer, dwRead);
} while (true);
return output;
}
int main() {
try {
std::cout << GetUrlData("/", "www.google.com");
}
catch (const std::exception& ex) {
std::cerr << "Exception: " << ex.what() << '\n';
}
}
你好,我正在尝试使用 WinInet 和 costum 用户代理下载一些东西,问题是我在 HttpSendRequestA 失败,错误 return 是 0
我不知道这个错误是什么意思我已经尝试查找它但没有出现
我使用 std::to_string(GetLastError());
得到错误
下面是代码
std::string GetUrlData(const std::string& resource, const std::string& host)
{
std::string output = "";
output.clear();
HINTERNET hIntSession = InternetOpenA("token", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
if (!hIntSession) {
return "ERROR: Session Cannot Start";
}
HINTERNET hHttpSession = InternetConnectA(hIntSession, host.c_str(), 80, 0, 0, INTERNET_SERVICE_HTTP, 0, NULL);
if (!hHttpSession) {
InternetCloseHandle(hIntSession);
return "ERROR: Cannot Connect To Internet";
}
HINTERNET hHttpRequest = HttpOpenRequestA(hHttpSession, "GET", resource.c_str(), 0, 0, 0, INTERNET_FLAG_RELOAD, 0);
if (!hHttpRequest) {
InternetCloseHandle(hHttpSession);
InternetCloseHandle(hIntSession);
return "ERROR: Http Request Failed";
}
// const char* szHeaders = "User-Agent: Mozzila\r\n";
if (!HttpSendRequestA(hHttpRequest, NULL, 0, NULL, 0)) {
InternetCloseHandle(hHttpRequest);
InternetCloseHandle(hHttpSession);
InternetCloseHandle(hIntSession);
return "ERROR: Http Request Failed 2";
}
char szBuffer[1024];
DWORD dwRead = 0;
do {
if (!InternetReadFile(hHttpRequest, szBuffer, sizeof(szBuffer), &dwRead)) {
InternetCloseHandle(hHttpRequest);
InternetCloseHandle(hHttpSession);
InternetCloseHandle(hIntSession);
return "ERROR: Cannot Download";
}
if (dwRead == 0)
break;
output.append(szBuffer, dwRead);
}
while (true);
return output;
}
我这样称呼这个函数std::string
data = GetUrlData("http://example.com/", "http://example.com/");
问题是你的 host
参数应该只是主机名,而不是完整的 URL 并且资源应该只是主机上的资源部分。
像这样:
std::string data = GetUrlData("/", "example.com");
旁注:您获得了最多三个需要手动释放的资源,并尝试确保使用 InternetCloseHandle()
释放它们,但它很快就会变得冗长,您最终可能会忘记一个。碰巧的是,如果您的 GetUrlData()
调用成功,您不会释放 任何 资源。
考虑将每个资源包装在 std::unique_ptr
中以使其自动释放。它不仅使它更安全,还使代码更易于阅读和维护。
示例:
#include <Windows.h>
#include <wininet.h>
#include <iostream>
#include <memory>
#include <stdexcept>
#include <string>
#include <type_traits>
// custom deleter for the resource
struct internet_deleter {
void operator()(HINTERNET hi) { InternetCloseHandle(hi); }
};
// the resource's wrapper type
using ihandle = std::unique_ptr<std::remove_pointer_t<HINTERNET>, internet_deleter>;
// functions for acquiring resources
auto RAII_InternetOpen() {
ihandle rv(InternetOpenA("token", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0));
if (rv) return rv;
throw std::runtime_error("InternetOpenA: " + std::to_string(GetLastError()));
}
auto RAII_InternetConnect(const ihandle& hIntSession, const std::string& host) {
ihandle rv(
InternetConnectA(hIntSession.get(), host.c_str(), 80, 0, 0,
INTERNET_SERVICE_HTTP, 0, NULL));
if (rv) return rv;
throw std::runtime_error("InternetConnectA: " + std::to_string(GetLastError()));
}
auto RAII_HttpOpenRequest(const ihandle& hHttpSession, const std::string& resource) {
ihandle rv(
HttpOpenRequestA(hHttpSession.get(), "GET", resource.c_str(), 0, 0, 0,
INTERNET_FLAG_RELOAD, 0));
if (rv) return rv;
throw std::runtime_error("HttpOpenRequestA: " + std::to_string(GetLastError()));
}
加上以上三个函数,GetUrlData()
函数变得更简单,不会泄露资源:
std::string GetUrlData(const std::string& resource, const std::string& host)
{
std::string output;
auto hIntSession = RAII_InternetOpen();
auto hHttpSession = RAII_InternetConnect(hIntSession, host);
auto hHttpRequest = RAII_HttpOpenRequest(hHttpSession, resource);
if (!HttpSendRequestA(hHttpRequest.get(), NULL, 0, NULL, 0))
throw std::runtime_error("HttpSendRequestA: " +
std::to_string(GetLastError()));
char szBuffer[1024];
DWORD dwRead = 0;
do {
if (!InternetReadFile(hHttpRequest.get(), szBuffer, sizeof(szBuffer), &dwRead))
throw std::runtime_error("InternetReadFile: " +
std::to_string(GetLastError()));
if (dwRead == 0)
break;
output.append(szBuffer, dwRead);
} while (true);
return output;
}
int main() {
try {
std::cout << GetUrlData("/", "www.google.com");
}
catch (const std::exception& ex) {
std::cerr << "Exception: " << ex.what() << '\n';
}
}