gpt4 book ai didi

c++ - WinInet 和 InternetOpen

转载 作者:行者123 更新时间:2023-11-28 05:38:30 26 4
gpt4 key购买 nike

文档指出可以多次调用 InternetOpen 而不会出现任何问题。我的问题是我应该多次调用 InternetCloseHandle 返回的句柄吗?

例如,我有一个名为 CAPIRequestContext 的类,它有一个由 InternetOpen 返回的句柄。我的每一个请求都有它自己的拷贝。现在,我在析构函数中调用了 InternetCloseHandle,所以它被调用了多次。

我想知道以下是否会导致问题:线程 A 创建一个 CAPIRequestObject,它调用 InternetOpen 并存储句柄。线程 B 做同样的事情,但在线程 A 退出之前超出范围,因此线程 B 在它自己的 CAPIRequestObject 中调用析构函数,它在由返回的句柄上调用 InternetCloseHandle互联网开放。

我应该在我的类的析构函数中删除对 InternetCloseHandle 的调用吗?至少对于 InternetHandle?我假设我应该为 HttpOpenRequest 返回的句柄调用 InternetCloseHandle。

我对 InternetConnect 返回的句柄有类似的疑问。这些句柄是共享的吗?

这是一些示例代码,减去一些我认为与问题无关的外部代码:

class CAPIClient;
class CAPIRequest
{
public:
CAPIRequestContext()
{
m_hConn = NULL;
m_hInternet = NULL;
m_hRequest = NULL;
}

~CAPIRequestContext()
{
if (m_hRequest) InternetCloseHandle(m_hRequest);
if (m_hConn) InternetCloseHandle(m_hConn);
if (m_hInternet) InternetCloseHandle(m_hInternet);
}

bool Init(const CAPIClient &client, const std::string &uri, const std::string &method)
{
ATLASSERT(!(m_hInternet || m_hConn || m_hRequest));
if (m_hInternet || m_hConn || m_hRequest) throw std::exception("Cannot init request more than once.");

bool success = false;
m_AuthToken = *client.m_pAuthToken;
URI = uri;
m_hInternet = InternetOpen("MyApp", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
DWORD requestTimeout = 60 * 1000; // Set timeout to 60 seconds instead of 30

if (m_hInternet)
{
InternetSetOption(m_hInternet, INTERNET_OPTION_RECEIVE_TIMEOUT, &requestTimeout, sizeof(requestTimeout));
m_hConn = InternetConnect(m_hInternet, (LPSTR)client.m_host.c_str(), client.m_port, NULL, NULL, INTERNET_SERVICE_HTTP, 0, (DWORD_PTR)this);
if (m_hConn) {
m_hRequest = HttpOpenRequest(m_hConn, method.c_str(), uri.c_str(), "HTTP/1.1", NULL, NULL, client.GetOpenRequestFlags(), 0);
}
if (m_hRequest)
{
success = true;
}
}
return success;
}
}

// There are additional calls like
// SendRequest
// GetData
// GetFullResponse

private:
// Added these methods to make sure I'm not copying the handles
enter code here
CAPIRequestContext(const CAPIRequestContext &other) = delete;
CAPIRequestContext& operator=(const CAPIRequestContext& other) = delete;

private:
HINTERNET m_hInternet;
HINTERNET m_hConn;
HINTERNET m_hRequest;

}

最佳答案

The documentation states that InternetOpen can be called multiple times without any issues. My question though is should I be calling InternetCloseHandle on handle returned by it multiple times?

是的,如 InternetOpen() 中所述文档:

After the calling application has finished using the HINTERNET handle returned by InternetOpen, it must be closed using the InternetCloseHandle function.

For example, I have a class I call CAPIRequestContext, which has a handle which is returned by InternetOpen. Each one of my requests has it's own copy. Right now, I call InternetCloseHandle in the destructor, so it gets called multiple times.

如果类的每个实例都调用 InternetOpen(),或者以其他方式获得唯一的 HINTERNET 的所有权,那将是一个正确的实现。

但是,请注意此类需要实现 Rule of Three .基本上,如果您必须提供析构函数来释放资源,您还需要提供复制构造函数和复制赋值运算符。

但是,您不能在同一个 HINTERNET 上多次调用 InternetCloseHandle(),因此您不能使用多个 CAPIRequestContext相同的 HINTERNET 并且它们都调用 InternetCloseHandle()1。因此,您的复制构造函数和复制赋值运算符必须:

  1. 从正在复制的源 CAPIRequestContext 获取 HINTERNET 的所有权。

  2. 完全禁用以防止将一个 CAPIRequestContext 复制到另一个。

在您的情况下,我会选择 #2。

1:您需要一个实例标志,指示哪个实例可以调用它,哪些不能。但这不是好的类设计。如果您需要共享一个 HINTERNET,您应该改为实现引用计数语义,例如由 std::shared_ptr 提供的。

I'm wondering if the following could cause issues: Thread A creates a CAPIRequestObject which calls InternetOpen and stores the handle. Thread B does the same, but then goes out of scope before Thread A exits, so Thread B calls the destructor in it's own CAPIRequestObject, which calls InternetCloseHandle on the handle returned by InternetOpen.

这是绝对安全的,前提是每个 CAPIRequestObject 都有自己的 HINTERNET

Should I remove the call to InternetCloseHandle in the destructors of my class?

不,如果每个类实例都拥有一个唯一的 HINTERNET

I assume I should call InternetCloseHandle for the handle returned by HttpOpenRequest.

是的,如 HttpOpenRequest() 中所述文档:

After the calling application has finished using the HINTERNET handle returned by HttpOpenRequest, it must be closed using the InternetCloseHandle function.

I have similar questions regarding the handle returned by InternetConnect. Are these handles shared?

每个 HINTERNET 都必须单独关闭。

关于c++ - WinInet 和 InternetOpen,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37666668/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com