Long polling vs WebSocket em C++: A batalha pelo tempo real
\n\nImagine: você está escrevendo um chat em C++, um terminal de bolsa de valores ou um sistema de monitoramento de servidores. O cliente precisa receber dados instantaneamente. As requisições HTTP "pergunta-resposta" não servem — são muito lentas e desperdiçam recursos. Existem duas saídas: Long polling (a velha escola) e WebSocket (o padrão moderno). O que escolher para um projeto C++? Vamos entender com exemplos reais.
\n\nComo funciona o Long polling em C++ (e por que ele ainda está vivo)
\n\nLong polling é uma emulação de tempo real sobre HTTP comum. O cliente envia uma requisição, o servidor não responde imediatamente, mas "fica pendurado" até que novos dados apareçam ou ocorra um timeout. Assim que os dados aparecem — o servidor envia a resposta, o cliente imediatamente envia uma nova requisição. Cria-se a ilusão de um fluxo contínuo.
\n\nEm C++, essa abordagem é frequentemente implementada usando libcurl no cliente e qualquer servidor HTTP (por exemplo, cpp-httplib ou Boost.Beast) no servidor. Veja como fica a parte clássica do servidor com Boost.Beast:
#include <boost/beast/core.hpp>\n#include <boost/beast/http.hpp>\n#include <boost/beast/version.hpp>\n#include <boost/asio.hpp>\n#include <queue>\n#include <mutex>\n#include <condition_variable>\n\nnamespace beast = boost::beast;\nnamespace http = beast::http;\nnamespace net = boost::asio;\n\nclass LongPollHandler {\n std::queue<std::string> messages_;\n std::mutex mtx_;\n std::condition_variable cv_;\npublic:\n // Método thread-safe para adicionar mensagem\n void push(const std::string& msg) {\n std::lock_guard<std::mutex> lock(mtx_);\n messages_.push(msg);\n cv_.notify_one();\n }\n\n // Manipulador de requisição Long Polling\n void handle(http::request<http::string_body>& req,\n http::response<http::string_body>& res) {\n std::unique_lock<std::mutex> lock(mtx_);\n // Aguarda nova mensagem ou timeout de 30 segundos\n if (cv_.wait_for(lock, std::chrono::seconds(30),\n [this](){ return !messages_.empty(); })) {\n std::string msg = messages_.front();\n messages_.pop();\n res.result(http::status::ok);\n res.body() = msg;\n } else {\n // Timeout — retorna resposta vazia\n res.result(http::status::no_content);\n res.body() = "";\n }\n res.prepare_payload();\n }\n};\n\nO cliente com libcurl ficará assim:
\n\n#include <curl/curl.h>\n#include <string>\n#include <iostream>\n\nsize_t write_callback(void* contents, size_t size, size_t nmemb, void* userp) {\n ((std::string*)userp)->append((char*)contents, size * nmemb);\n return size * nmemb;\n}\n\nvoid long_poll_loop(CURL* curl, const std::string& url) {\n std::string response;\n while (true) {\n curl_easy_setopt(curl, CURLOPT_URL, url.c_str());\n curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback);\n curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response);\n curl_easy_setopt(curl, CURLOPT_TIMEOUT, 35L); // um pouco maior que o timeout do servidor\n\n CURLcode res = curl_easy_perform(curl);\n if (res == CURLE_OK && !response.empty()) {\n std::cout << "Recebido: " << response << std::endl;\n response.clear();\n // envia imediatamente uma nova requisição\n continue;\n }\n // Em caso de erro, aguarda 5 segundos e repete\n std::this_thread::sleep_for(std::chrono::seconds(5));\n }\n}\n\nVantagens do Long polling em C++: Simplicidade, compatibilidade com todos os proxies e firewalls, não requer bibliotecas especiais. Desvantagens: Grande quantidade de cabeçalhos HTTP, atrasos no estabelecimento de conexão (TCP ha