【发布时间】:2015-09-01 18:05:40
【问题描述】:
我编写了一个使用 WinInet 库的程序。该程序每天运行约 8-12 小时。首先它连接到互联网,然后它使用 FTP 下载/上传文件。之后它开始一个循环,在不同的时间间隔内最多启动两个线程。两个线程都在向同一台服务器发送GET-requests,看起来像这样:
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-Handles 是否无效?
[EDIT] 同时,我怀疑我的程序导致了连接问题,因为我在家中的有线网络上也没有互联网访问权限!我犯了什么错误吗?
【问题讨论】:
-
您在滥用
GetLastError()。除非首先报告实际失败(InternetOpen()返回 NULL,InternetConnect()返回 NULL 等),否则请勿调用它,否则您可能会看到早期 API 调用的错误代码,这些错误代码与您正在调用的 API 无关。除非明确记录,大多数 API 函数不会在输入时重置GetLastError(),或者如果成功则更新GetLastError()。 -
@RemyLebeau 好的,谢谢,我会针对这种误用修改我的程序代码!
-
@RemyLebeau 现在编辑了代码。关于错误的任何想法?
-
您有多个线程共享
hInternetOpen和hHTTPConnection句柄,通过单个HTTP 连接在多个线程中发送HTTP 请求,而无需序列化对连接的访问。这是灾难的秘诀。因此,要么序列化对连接的访问以避免竞争条件,要么为每个线程提供自己的本地连接。 -
@RemyLebeau 好的,谢谢!如果我给每个线程自己的连接怎么样?如果同一个线程每 5 秒启动一次,会不会有问题?我所谓的“灾难食谱”会不会是问题 2 中所示的连接行为的原因?