套接字仍处于CLOSE_WAIT状态。

4

当应用程序启动时,我使用Wininet与服务器进行检查。

问题在于,在调用CloseInternetHandle后,套接字状态仍然是CLOSE_WAIT,如netstat所示,并且最糟糕的是它永远不会改变状态。

这是我正在使用的简单代码。我做错了什么吗?

hInternet = InternetOpen(NULL, INTERNETOPENTYPEPRECONFIG, NULL, NULL, 0);
    if (hInternet)
    {
        hFile = InternetOpenUrl(hInternet, url, NULL, 0, INTERNETFLAGRELOAD, 0);

        InternetReadFile(hFile, &buffer, 20, &btsRead);
        InternetCloseHandle(hFile);
        InternetCloseHandle(hInternet);
    }

你在宣布它“永远不会”改变之前等待了多久? - Mat
应用程序正在运行还是调试器已暂停?CLOSE_WAIT 意味着应用程序尚未关闭套接字。 - usr
但是我正在关闭它,正如你所看到的,它没有在调试器中运行。 - opc0de
您没有关闭TCP连接,而是关闭了Internet句柄。WinInet API肯定支持HTTP keep-alive和连接池。暂停调试器会阻止清理工作。 - usr
@usr,正如我之前所说,它没有在调试器中运行,那么我该如何关闭TCP连接? - opc0de
1个回答

2
WinInet尝试在可能的情况下重复使用套接字,因此即使您释放了句柄,它也可以选择保持套接字处于活动状态,以便下一次调用InternetOpen。大多数情况下,这是一件好事,您不需要担心它。
这不是句柄泄漏。如果您将代码放在循环中并查看netstat中的本地端口号,则可以看到相同的套接字一遍又一遍地被重用。当进程完成时,WinInet将正确关闭套接字。
如果您真的需要立即关闭它,可以在最终的InternetCloseHandle后调用InternetSetOption以欺骗WinInet执行此操作:
...
InternetCloseHandle(hInternet);
InternetSetOption(NULL, INTERNET_OPTION_SETTINGS_CHANGED, NULL, 0);

这样做告诉WinInet全局设置已更改(例如在注册表中),因此它别无选择,只能关闭所有套接字并重置自己。但是,显然这不是预期的用法,并且如果您正在使用WinInet进行大量连接,则会产生一些性能影响。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接