0

我希望能够向我的网站发出我的 c++ 应用程序当前正在运行的信号。到目前为止,我所做的是使用 libcurl 使用一些获取参数来联系我网站上的 PHP 文件。
这是 C++ 代码:

curl_global_init(CURL_GLOBAL_ALL);
CURL * handle = curl_easy_init();
CURLcode result;
std::string url, contents;

std::cin >> url;

curl_easy_setopt(handle, CURLOPT_URL, url);
curl_easy_setopt(handle, CURLOPT_ERRORBUFFER, &errorBuf[0]);
curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, writefunc);
curl_easy_setopt(handle, CURLOPT_WRITEDATA, &contents);

while(true)
{
    time_t startOfLoop = time(0);
    //Ping page
    result = curl_easy_perform(handle);

    if(result == 0)
        std::cout << "[" << time(0) << "]: Pinged \"" << url << "\" ok!\r\n";
    else
    {
        std::cout << "[" << time(0) << "]: Pinged \"" << url << "\" **ERROR: " << errorBuf << " [Error Code: " << result << "]\r\n";
    }

    //Pause until 5 seconds has passed
    while(difftime(time(0), startOfLoop) < 5) {}
}
curl_easy_cleanup(handle);

然后,PHP 文件写入 MySQLi 数据库,表明程序已 ping 入。此页面在应用程序中每 5 秒加载一次,并且运行良好。

但是,在一定时间后,网站停止接受请求。http://www.downforeveryoneorjustme.com/说该网站仍然在线,但我得到Oops! Google Chrome could not connect了,并且 curl 应用程序只是吐出**ERROR: Failed connect to [site-url]:80; No error [Error Code: 7]一段时间,直到网站决定再次开始允许请求。

这是我使用的虚拟主机的问题吗?(000webhost),我是否只需要升级到具有更多带宽的更好的虚拟主机?

还是我以错误的方式解决这个问题?有没有更好的方法从 C++ 应用程序联系我的网站?

任何帮助将不胜感激。
谢谢!

4

1 回答 1

2

你所描述的听起来就像服务器池中所有可用的 TCP 套接字都用完了(例如进入 ESTABLISHED 或 TIME_WAIT 状态)。一旦一个套接字被关闭,它就会进入 TIME_WAIT 状态一段时间(通常是 4 分钟)。在此时间之后,它可以再次使用。因此,如果您的服务器配置了非常少量的套接字(<250),并且 curl 每次都使用新的套接字,那么这可能是问题所在。

如果您有访问权限,您可以netstat在服务器上运行以检查套接字的当前状态。

但是,默认情况下 curl 应该使用持久保持连接。根据文档curl_easy_perform 应该尝试重用连接,所以理论上你不应该看到这个问题(除非服务器没有配置为使用 keep-alives 我想)。

此外,您的代码有一些错误,所以我想知道是否会发生一些未定义的行为。我建议修复这些错误,看看问题是否仍然存在。

  1. 使用url.c_str()而不是urlcurl_easy_setopt(handle, CURLOPT_URL, url);

  2. 传递一个指向缓冲区的指针,而不是一个字符串curl_easy_setopt(handle, CURLOPT_WRITEDATA, &contents);

  3. 根据文档,应该在每次调用之前调用curl_easy_perform,所以尝试在循环内移动 setopts。curl_easy_setoptcurl_easy_perform

我将您的代码复制到一个测试应用程序中并对其进行了修改以在我的系统上进行测试。它工作得很好。这是我的完整代码:

#include <iostream>
#include <string>
#include <thread>
#include <curl/curl.h>

using namespace std;

char errorBuf[CURL_ERROR_SIZE];
char contents[CURL_MAX_WRITE_SIZE];
std::string url;
size_t received_len = 0;

size_t write_func( char *ptr, size_t size, size_t nmemb, void *userdata)
{
    size_t len = size*nmemb;
    received_len += len;
    return len;
}

int main()
{
    curl_global_init(CURL_GLOBAL_ALL);
    CURL * handle = curl_easy_init();
    CURLcode result;

    cout << "Enter URL:";
    cin >> url;

    while(true)
    {
        received_len = 0;

        // Set options before each call to curl_easy_perform()
        curl_easy_setopt(handle, CURLOPT_URL, url.c_str());
        curl_easy_setopt(handle, CURLOPT_ERRORBUFFER, errorBuf);
        curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, write_func);
        curl_easy_setopt(handle, CURLOPT_WRITEDATA, contents);

        // Invoke the URL
        if((result = curl_easy_perform(handle)) == 0)
            cout << "[" << time(0) << "]: \"" << url << "\" Received " << received_len << " bytes ok!\n";
        else
            std::cout << "[" << time(0) << "]: \"" << url << "\" **ERROR: " << errorBuf << " [Error Code: " << result << "]\n";

        // Pause until 5 seconds has passed
        std::this_thread::sleep_for(std::chrono::seconds(5));
    }

    // NOTE: This will never be called
    curl_easy_cleanup(handle);

    return 0;
}
于 2013-10-24T22:01:06.613 回答