C++ WinInet InternetCloseHandle 崩溃
C++ WinInet InternetCloseHandle crash
我编写了一个使用 WinInet 库的程序。该程序每天运行约 8-12 小时。首先它连接到互联网,然后它使用 FTP 到 down-/up-load 文件。之后它开始一个循环,在不同的时间间隔启动最多两个线程。两个线程都在对同一台服务器执行 GET
请求,并且看起来像这样:
private void Thread()
{
if(!InternetGetConnectedState(NULL, NULL))
{
connectToInternet();
}
// some code...
HINTERNET httpOpenRequest = HttpOpenRequest(
hHTTPConnection, // InternetConnect-Handle
L"GET", // HTTP-Verb
request_target, // FileName
L"HTTP/1.1", // HTTP-Version
NULL, // Referer
NULL, // AcceptTypes
INTERNET_FLAG_RELOAD, // Flags
0 // Context
);
BOOL httpsRequest = HttpSendRequest(
httpOpenRequest, // Handle of HttpOpenRequest
NULL, // Headers
0, // Headers-Length
NULL, // Optional
0 // Optional-Length
);
InternetCloseHandle(httpOpenRequest); // App-Crash sometimes here!
}
我的 connectToInternet
-函数在这里:
int connectToInternet()
{
DWORD InetTest1 = 16000;
while (InetTest1 != 0)
{
InetTest1 = InternetAttemptConnect(0);
// wait 1 second for next attempt
if (InetTest1 != 0)
{
Sleep(1000);
}
}
BOOL InetTest2 = FALSE;
while (!InetTest2)
{
InetTest2 = InternetCheckConnection(
L"http://www.example.com", // URL
FLAG_ICC_FORCE_CONNECTION, // Flags
0 // Reserved
);
// wait 1 second for next attempt
if (!InetTest2)
{
Sleep(1000);
}
}
while (hInternetOpen == NULL)
{
hInternetOpen = InternetOpen(
L"Custom-Agent", // Agent
INTERNET_OPEN_TYPE_DIRECT, // AccessType
NULL, // ProxyName
NULL, // ProxyBypass
0 // Flags
);
// wait 1 second for next attempt
if (hInternetOpen == NULL)
{
Sleep(1000);
}
}
while (hHTTPConnection == NULL)
{
hHTTPConnection = InternetConnect(
hInternetOpen, // InternetOpen-Handle
L"www.example.com", // ServerName
INTERNET_DEFAULT_HTTP_PORT, // ServerPort
NULL, // Username
NULL, // Password
INTERNET_SERVICE_HTTP, // Service
0, // Flags
0 // Context
);
// wait 1 second for next attempt
if (hHTTPConnection == NULL)
{
Sleep(1000);
}
}
return 0;
}
(我在这里找到的这个函数的基本工作流程:https://msdn.microsoft.com/en-us/library/windows/desktop/aa383996(v=vs.85).aspx)
现在问题:
Q1: 当两个线程之一调用 InternetCloseHandle(httpOpenRequest)
时,我似乎很少遇到应用程序崩溃。我找不到这些应用程序崩溃的原因...您有什么想法吗?
Q2: 程序所在的笔记本电脑 运行 似乎有互联网连接问题,因为它失去了连接经常持续几秒钟到几分钟甚至几个小时。因此,如果 InternetGetConnectedState(NULL, NULL)
是 false
,我首先在两个线程中调用 connectToInternet()
。这一步是必需的,还是如果我不调用连接函数它也能工作?如果连接中断,全局 HINTERNET
-句柄是否无效?
[编辑] 与此同时,我怀疑我的程序导致了连接问题,因为我也没有互联网-在家里访问我的有线网络!我有没有犯错?
看来我的问题是由多个线程运行同时尝试调用InternetCloseHandle()
引起的。
同时我重写了我的代码。我也试图让 Remy Lebeau 的评论参与进来。我的代码现在看起来像以下示例:
void Thread()
{
// access-control
if (ThreadRunning == true)
{
return 99;
}
ThreadRunning = true;
// variables
HINTERNET hInternetOpen = NULL;
HINTERNET hHTTPConnection = NULL;
HINTERNET httpOpenRequest = NULL;
int connectionAttempts;
string target_string;
wstring target_wstring;
LPCWSTR request_target;
BOOL httpSendRequestSuccessful;
BOOL httpQueryInfoReceived;
DWORD statusCode = 0;
DWORD statusCodeLen = sizeof(statusCode);
BOOL dataAvailable;
DWORD numberOfBytesAvailable;
BOOL internetReadFileSuccessful;
char buffer[4096] = { "" };
DWORD numberOfBytesRead;
// Connect to Internet
connectionAttempts = 0;
DWORD InetTest1 = 16000;
while (InetTest1 != 0)
{
InetTest1 = InternetAttemptConnect(0);
if (InetTest1 != 0)
{
connectionAttempts++;
// prevent an infinite loop
if (connectionAttempts >= 5)
{
// reset access-control
ThreadRunning = false;
return 1;
}
// wait 1 second if it fails
Sleep(1000);
}
}
// reset connectionAttempts
connectionAttempts = 0;
BOOL InetTest2 = FALSE;
while (!InetTest2)
{
InetTest2 = InternetCheckConnection(
L"http://www.example.com", // URL
FLAG_ICC_FORCE_CONNECTION, // Flags
0 // Reserved
);
if (InetTest2 == FALSE)
{
connectionAttempts++;
// prevent an infinite loop
if (connectionAttempts >= 5)
{
// reset access-control
ThreadRunning = false;
return 2;
}
// wait 1 second if it fails
Sleep(1000);
}
}
// reset connectionAttempts
connectionAttempts = 0;
while (hInternetOpen == NULL)
{
hInternetOpen = InternetOpen(
L"Custom-Agent", // Agent
INTERNET_OPEN_TYPE_DIRECT, // AccessType
NULL, // ProxyName
NULL, // ProxyBypass
0 // Flags
);
if (hInternetOpen == NULL)
{
connectionAttempts++;
// prevent an infinite loop
if (connectionAttempts >= 5)
{
// reset access-control
ThreadRunning = false;
return 3;
}
// wait 1 second if it fails
Sleep(1000);
}
}
// reset connectionAttempts
connectionAttempts = 0;
while (hHTTPConnection == NULL)
{
hHTTPConnection = InternetConnect(
hInternetOpen, // InternetOpen-Handle
L"www.example.com", // ServerName
INTERNET_DEFAULT_HTTP_PORT, // ServerPort
NULL, // Username
NULL, // Password
INTERNET_SERVICE_HTTP, // Service
0, // Flags
0 // Context
);
if (hHTTPConnection == NULL)
{
connectionAttempts++;
// prevent an infinite loop
if (connectionAttempts >= 5)
{
// reset access-control
onlineSettingsThreadRunning = false;
// Handle-Cleanup
InternetCloseHandle(hInternetOpen);
return 4;
}
// wait 1 second if it fails
Sleep(1000);
}
}
// some code...
// open HTTP-Request
httpOpenRequest = HttpOpenRequest(
hHTTPConnection, // InternetConnect-Handle
L"GET", // HTTP-Verb (GET or POST)
request_target, // FileName
L"HTTP/1.1", // HTTP-Version
NULL, // Referer
NULL, // AcceptTypes
INTERNET_FLAG_RELOAD, // Flags
0 // Context
);
if (httpOpenRequest == NULL)
{
// Handle-Cleanup
InternetCloseHandle(hHTTPConnection);
InternetCloseHandle(hInternetOpen);
// reset access-control
onlineSettingsThreadRunning = false;
return 5;
}
// send HTTP-Request
httpSendRequestSuccessful = HttpSendRequest(
httpOpenRequest, // Handle von HttpOpenRequest
NULL, // Headers
0, // Headers-Length
NULL, // Optional
0 // Optional-Length
);
if (httpSendRequestSuccessful == FALSE)
{
// Handle-CleanUp
InternetCloseHandle(httpOpenRequest);
InternetCloseHandle(hHTTPConnection);
InternetCloseHandle(hInternetOpen);
// reset access-control
onlineSettingsThreadRunning = false;
return 6;
}
// read Server-Status
httpQueryInfoReceived = HttpQueryInfo(
httpOpenRequest,
HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER,
&statusCode,
&statusCodeLen,
NULL
);
if (httpQueryInfoReceived == FALSE || statusCode != 200)
{
// Handle-CleanUp
InternetCloseHandle(httpOpenRequest);
InternetCloseHandle(hHTTPConnection);
InternetCloseHandle(hInternetOpen);
// reset access-control
onlineSettingsThreadRunning = false;
return 7;
}
// test, how much bytes are readable
dataAvailable = InternetQueryDataAvailable(
httpOpenRequest,
&numberOfBytesAvailable,
0,
0
);
if (dataAvailable == FALSE)
{
// Handle-CleanUp
InternetCloseHandle(httpOpenRequest);
InternetCloseHandle(hHTTPConnection);
InternetCloseHandle(hInternetOpen);
// reset access-control
onlineSettingsThreadRunning = false;
return 8;
}
// some code...
// Close internet-connection
InternetCloseHandle(httpOpenRequest);
InternetCloseHandle(hHTTPConnection);
InternetCloseHandle(hInternetOpen);
// reset access-control
ThreadRunning = false;
return 0;
}
所以我的 connectToInternet()
-函数不再存在了。它现在是每个需要互联网访问的线程的一部分。它也不再使用 GetLastError()
,因为这可能会产生错误的结果...
我仍在测试我的代码,但它似乎很有前途:-)
我编写了一个使用 WinInet 库的程序。该程序每天运行约 8-12 小时。首先它连接到互联网,然后它使用 FTP 到 down-/up-load 文件。之后它开始一个循环,在不同的时间间隔启动最多两个线程。两个线程都在对同一台服务器执行 GET
请求,并且看起来像这样:
private void Thread()
{
if(!InternetGetConnectedState(NULL, NULL))
{
connectToInternet();
}
// some code...
HINTERNET httpOpenRequest = HttpOpenRequest(
hHTTPConnection, // InternetConnect-Handle
L"GET", // HTTP-Verb
request_target, // FileName
L"HTTP/1.1", // HTTP-Version
NULL, // Referer
NULL, // AcceptTypes
INTERNET_FLAG_RELOAD, // Flags
0 // Context
);
BOOL httpsRequest = HttpSendRequest(
httpOpenRequest, // Handle of HttpOpenRequest
NULL, // Headers
0, // Headers-Length
NULL, // Optional
0 // Optional-Length
);
InternetCloseHandle(httpOpenRequest); // App-Crash sometimes here!
}
我的 connectToInternet
-函数在这里:
int connectToInternet()
{
DWORD InetTest1 = 16000;
while (InetTest1 != 0)
{
InetTest1 = InternetAttemptConnect(0);
// wait 1 second for next attempt
if (InetTest1 != 0)
{
Sleep(1000);
}
}
BOOL InetTest2 = FALSE;
while (!InetTest2)
{
InetTest2 = InternetCheckConnection(
L"http://www.example.com", // URL
FLAG_ICC_FORCE_CONNECTION, // Flags
0 // Reserved
);
// wait 1 second for next attempt
if (!InetTest2)
{
Sleep(1000);
}
}
while (hInternetOpen == NULL)
{
hInternetOpen = InternetOpen(
L"Custom-Agent", // Agent
INTERNET_OPEN_TYPE_DIRECT, // AccessType
NULL, // ProxyName
NULL, // ProxyBypass
0 // Flags
);
// wait 1 second for next attempt
if (hInternetOpen == NULL)
{
Sleep(1000);
}
}
while (hHTTPConnection == NULL)
{
hHTTPConnection = InternetConnect(
hInternetOpen, // InternetOpen-Handle
L"www.example.com", // ServerName
INTERNET_DEFAULT_HTTP_PORT, // ServerPort
NULL, // Username
NULL, // Password
INTERNET_SERVICE_HTTP, // Service
0, // Flags
0 // Context
);
// wait 1 second for next attempt
if (hHTTPConnection == NULL)
{
Sleep(1000);
}
}
return 0;
}
(我在这里找到的这个函数的基本工作流程:https://msdn.microsoft.com/en-us/library/windows/desktop/aa383996(v=vs.85).aspx)
现在问题:
Q1: 当两个线程之一调用 InternetCloseHandle(httpOpenRequest)
时,我似乎很少遇到应用程序崩溃。我找不到这些应用程序崩溃的原因...您有什么想法吗?
Q2: 程序所在的笔记本电脑 运行 似乎有互联网连接问题,因为它失去了连接经常持续几秒钟到几分钟甚至几个小时。因此,如果 InternetGetConnectedState(NULL, NULL)
是 false
,我首先在两个线程中调用 connectToInternet()
。这一步是必需的,还是如果我不调用连接函数它也能工作?如果连接中断,全局 HINTERNET
-句柄是否无效?
[编辑] 与此同时,我怀疑我的程序导致了连接问题,因为我也没有互联网-在家里访问我的有线网络!我有没有犯错?
看来我的问题是由多个线程运行同时尝试调用InternetCloseHandle()
引起的。
同时我重写了我的代码。我也试图让 Remy Lebeau 的评论参与进来。我的代码现在看起来像以下示例:
void Thread()
{
// access-control
if (ThreadRunning == true)
{
return 99;
}
ThreadRunning = true;
// variables
HINTERNET hInternetOpen = NULL;
HINTERNET hHTTPConnection = NULL;
HINTERNET httpOpenRequest = NULL;
int connectionAttempts;
string target_string;
wstring target_wstring;
LPCWSTR request_target;
BOOL httpSendRequestSuccessful;
BOOL httpQueryInfoReceived;
DWORD statusCode = 0;
DWORD statusCodeLen = sizeof(statusCode);
BOOL dataAvailable;
DWORD numberOfBytesAvailable;
BOOL internetReadFileSuccessful;
char buffer[4096] = { "" };
DWORD numberOfBytesRead;
// Connect to Internet
connectionAttempts = 0;
DWORD InetTest1 = 16000;
while (InetTest1 != 0)
{
InetTest1 = InternetAttemptConnect(0);
if (InetTest1 != 0)
{
connectionAttempts++;
// prevent an infinite loop
if (connectionAttempts >= 5)
{
// reset access-control
ThreadRunning = false;
return 1;
}
// wait 1 second if it fails
Sleep(1000);
}
}
// reset connectionAttempts
connectionAttempts = 0;
BOOL InetTest2 = FALSE;
while (!InetTest2)
{
InetTest2 = InternetCheckConnection(
L"http://www.example.com", // URL
FLAG_ICC_FORCE_CONNECTION, // Flags
0 // Reserved
);
if (InetTest2 == FALSE)
{
connectionAttempts++;
// prevent an infinite loop
if (connectionAttempts >= 5)
{
// reset access-control
ThreadRunning = false;
return 2;
}
// wait 1 second if it fails
Sleep(1000);
}
}
// reset connectionAttempts
connectionAttempts = 0;
while (hInternetOpen == NULL)
{
hInternetOpen = InternetOpen(
L"Custom-Agent", // Agent
INTERNET_OPEN_TYPE_DIRECT, // AccessType
NULL, // ProxyName
NULL, // ProxyBypass
0 // Flags
);
if (hInternetOpen == NULL)
{
connectionAttempts++;
// prevent an infinite loop
if (connectionAttempts >= 5)
{
// reset access-control
ThreadRunning = false;
return 3;
}
// wait 1 second if it fails
Sleep(1000);
}
}
// reset connectionAttempts
connectionAttempts = 0;
while (hHTTPConnection == NULL)
{
hHTTPConnection = InternetConnect(
hInternetOpen, // InternetOpen-Handle
L"www.example.com", // ServerName
INTERNET_DEFAULT_HTTP_PORT, // ServerPort
NULL, // Username
NULL, // Password
INTERNET_SERVICE_HTTP, // Service
0, // Flags
0 // Context
);
if (hHTTPConnection == NULL)
{
connectionAttempts++;
// prevent an infinite loop
if (connectionAttempts >= 5)
{
// reset access-control
onlineSettingsThreadRunning = false;
// Handle-Cleanup
InternetCloseHandle(hInternetOpen);
return 4;
}
// wait 1 second if it fails
Sleep(1000);
}
}
// some code...
// open HTTP-Request
httpOpenRequest = HttpOpenRequest(
hHTTPConnection, // InternetConnect-Handle
L"GET", // HTTP-Verb (GET or POST)
request_target, // FileName
L"HTTP/1.1", // HTTP-Version
NULL, // Referer
NULL, // AcceptTypes
INTERNET_FLAG_RELOAD, // Flags
0 // Context
);
if (httpOpenRequest == NULL)
{
// Handle-Cleanup
InternetCloseHandle(hHTTPConnection);
InternetCloseHandle(hInternetOpen);
// reset access-control
onlineSettingsThreadRunning = false;
return 5;
}
// send HTTP-Request
httpSendRequestSuccessful = HttpSendRequest(
httpOpenRequest, // Handle von HttpOpenRequest
NULL, // Headers
0, // Headers-Length
NULL, // Optional
0 // Optional-Length
);
if (httpSendRequestSuccessful == FALSE)
{
// Handle-CleanUp
InternetCloseHandle(httpOpenRequest);
InternetCloseHandle(hHTTPConnection);
InternetCloseHandle(hInternetOpen);
// reset access-control
onlineSettingsThreadRunning = false;
return 6;
}
// read Server-Status
httpQueryInfoReceived = HttpQueryInfo(
httpOpenRequest,
HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER,
&statusCode,
&statusCodeLen,
NULL
);
if (httpQueryInfoReceived == FALSE || statusCode != 200)
{
// Handle-CleanUp
InternetCloseHandle(httpOpenRequest);
InternetCloseHandle(hHTTPConnection);
InternetCloseHandle(hInternetOpen);
// reset access-control
onlineSettingsThreadRunning = false;
return 7;
}
// test, how much bytes are readable
dataAvailable = InternetQueryDataAvailable(
httpOpenRequest,
&numberOfBytesAvailable,
0,
0
);
if (dataAvailable == FALSE)
{
// Handle-CleanUp
InternetCloseHandle(httpOpenRequest);
InternetCloseHandle(hHTTPConnection);
InternetCloseHandle(hInternetOpen);
// reset access-control
onlineSettingsThreadRunning = false;
return 8;
}
// some code...
// Close internet-connection
InternetCloseHandle(httpOpenRequest);
InternetCloseHandle(hHTTPConnection);
InternetCloseHandle(hInternetOpen);
// reset access-control
ThreadRunning = false;
return 0;
}
所以我的 connectToInternet()
-函数不再存在了。它现在是每个需要互联网访问的线程的一部分。它也不再使用 GetLastError()
,因为这可能会产生错误的结果...
我仍在测试我的代码,但它似乎很有前途:-)