- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
文档指出可以多次调用 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 byInternetOpen
, it must be closed using theInternetCloseHandle
function.
For example, I have a class I call
CAPIRequestContext
, which has a handle which is returned byInternetOpen
. Each one of my requests has it's own copy. Right now, I callInternetCloseHandle
in the destructor, so it gets called multiple times.
如果类的每个实例都调用 InternetOpen()
,或者以其他方式获得唯一的 HINTERNET
的所有权,那将是一个正确的实现。
但是,请注意此类需要实现 Rule of Three .基本上,如果您必须提供析构函数来释放资源,您还需要提供复制构造函数和复制赋值运算符。
但是,您不能在同一个 HINTERNET
上多次调用 InternetCloseHandle()
,因此您不能使用多个 CAPIRequestContext
相同的 HINTERNET
并且它们都调用 InternetCloseHandle()
1。因此,您的复制构造函数和复制赋值运算符必须:
从正在复制的源 CAPIRequestContext
获取 HINTERNET
的所有权。
完全禁用以防止将一个 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 byHttpOpenRequest
, it must be closed using theInternetCloseHandle
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/
文档指出可以多次调用 InternetOpen 而不会出现任何问题。我的问题是我应该多次调用 InternetCloseHandle 返回的句柄吗? 例如,我有一个名为 CAPIRequestCont
我正在使用 wininet 连接到需要客户端证书的 URL。为了测试我的“自动纠错”,我在没有客户端证书的情况下进行此连接,行为是调用我的 SelectCertificate 函数。 我故意不将所有参
我是一名优秀的程序员,十分优秀!