在 wininet 中使用 InternetConnect() API 后,如何判断我是不是仍然连接?

Posted

技术标签:

【中文标题】在 wininet 中使用 InternetConnect() API 后,如何判断我是不是仍然连接?【英文标题】:After using the InternetConnect() API in wininet how can I tell if I'm still connected?在 wininet 中使用 InternetConnect() API 后,如何判断我是否仍然连接? 【发布时间】:2016-06-08 15:46:39 【问题描述】:

我使用 WinINet API 中的 InternetConnect() 方法。我很好地连接到我的 FTP 服务器,没有任何问题。连接后,我等待了大约 1 分钟,并且由于没有预期的活动,服务器断开了我的连接。然后我尝试发送一个文件,但我没有连接。

有没有办法“检查” FTP 连接以查看我是否仍然连接?或者有什么方法可以让我附加一个事件来告诉我什么时候断开连接?

【问题讨论】:

编写自己的方法来检查 FTP 连接:即if (!FTPConnection) throw new Exception("Exception Text") 哇,这有点含糊。 FTPConnection 是什么类型的对象?你从哪里得到它? @jdweng 我知道有人会这么建议。 :) 我只是使用一个简单的例子来实现相同的最终结果。当有人拔掉电缆或互联网连接中断时会发生什么?如果服务器管理员强制断开连接怎么办?无论哪种方式,KeepAlive 都不是有效的解决方案。 获取状态也不行。断开电缆,客户端仍然会报告连接已关闭,也不会报告互联网是否出现故障。使用 ping 会让人更有信心,但永远不会完全有信心。 【参考方案1】:

我没有将wininet 用于FTP,我使用的是类,而不是直接使用全局函数。但我怀疑 CFtpConnection 在这方面的行为与 CHttpConnection 相同。无论如何,您可能会从我对后者的发现中学到一些东西。

CHttpConnection 似乎是一个高级抽象的连接。当我开始时,我希望它的成员函数在服务器关闭底层套接字(超时)后抛出异常。我现在知道得更好,或者至少不相信。套接字的正常关闭不会导致在这种高级 wininet 中引发异常。您可能会怀疑检查 wininet 错误代码:没有与关闭连接的服务器相对应的代码。

我对此进行了实验,发现:服务器关闭套接字(超时)被认为是正常的,不会导致抛出异常。您可以继续使用 CHttpConnection 而不必担心这一点。如果需要,它会简单地重新连接而不会提醒您。因此,一旦您调用了 GetHttpConnection 并获得了 CHttpConnection 对象,它通常会一直持续下去!

可能抛出的异常 ERROR_INTERNET_CONNECTION_ABORTED 和 ERROR_INTERNET_CONNECTION_RESET 是由异常情况引起的,例如 f.ex。代理服务器崩溃或有人不小心将电源插头拔到调制解调器上。服务器因超时而关闭套接字被认为是正常的,并且对 wininet 类的用户是透明的。

所以暂定的结论是你不必担心连接被服务器关闭。如果发生这种情况,CHttpConnection 将在后台重新连接,您将不会被打扰。您可以假装连接始终保持打开状态 - 对于 wininet 类的用户来说似乎是这样。

考虑以下实验。打开一个连接,然后每分钟发送一次请求。一旦抛出异常,该函数就会返回。但如果不是,那么它会永远循环。我在两个不同的网站上尝试过: 永远不会抛出异常!尽管请求之间有一整分钟的不活动。

int httpclient::test(string host)

    int flags = INTERNET_FLAG_RELOAD;
    int port = INTERNET_DEFAULT_HTTP_PORT;
    CHttpConnection *connection = session.GetHttpConnection(host.cstring(),flags,port);
    int secs = 0;
    while (true)
    
        CHttpFile *fil;
        try 
        
            fil = connection->OpenRequest(CHttpConnection::HTTP_VERB_HEAD, "index.htm",
                                            0,1,0, "HTTP/1.1", flags);
        
        catch (CInternetException *exc)
        
            connection->Close();
            int feil = exc->m_dwError;
            exc->Delete();
            return -feil;
               
        fil->AddRequestHeaders("Connection: Keep-Alive");
        try
        
            fil->SendRequest();
        
        catch (CInternetException *exc)
        
            connection->Close();
            int feil = exc->m_dwError;
            exc->Delete();
            return feil;
               
        fil->Close();
        Sleep(60 * 1000);
        secs += 60;
        printf("%u seconds passed\n", secs);
    
    return 0;

对这一切持保留态度。 wininet 的文档记录很差,我所知道的只是实验教给我的。

【讨论】:

以上是关于在 wininet 中使用 InternetConnect() API 后,如何判断我是不是仍然连接?的主要内容,如果未能解决你的问题,请参考以下文章

在 wininet 中使用 InternetConnect() API 后,如何判断我是不是仍然连接?

Delphi - 使用 Wininet 下载文件?

WinInet 帖子的简单包装函数(在 Delphi 中)

如何使用 wininet 强制执行 tls 1.x

在 C++ 中使用 Wininet 发送 POST 请求时的编码问题

WinInet 能否返回正在使用的 TLS