c++ - Boost 连续发布请求 CPP

#include <boost/beast/core.hpp>
#include <boost/beast/http.hpp>
#include <boost/beast/version.hpp>
#include <boost/asio/strand.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/beast/http/basic_dynamic_body.hpp>



#include <boost/json.hpp>
#include <boost/json/src.hpp>
#include <boost/beast.hpp>

#include <Windows.h>

//#include <boost/beast/core/multi_buffer.hpp>

#include <opencv2/opencv.hpp>
#include <opencv2/calib3d/calib3d.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>

#include <cstdlib>
#include <iostream>
#include <memory>
#include <string>
#include <map>
#include <vector>



namespace beast = boost::beast;         // from <boost/beast.hpp>
namespace http = beast::http;           // from <boost/beast/http.hpp>
namespace net = boost::asio;            // from <boost/asio.hpp>
using tcp = boost::asio::ip::tcp;       // from <boost/asio/ip/tcp.hpp>
namespace bj = boost::json;
using boost::asio::deadline_timer;

class Client :public std::enable_shared_from_this<Client>
{
    tcp::resolver resolver_;
    beast::tcp_stream stream_;
    beast::flat_buffer buffer_; // (Must persist between reads)
    http::request < http::string_body> req_;
    http::response<http::string_body> res_;
    int m_outer;

    public:
        // Objects are constructed with a strand to
        // ensure that handlers do not execute concurrently.
        explicit
            Client(net::io_context& ioc)
            : resolver_(net::make_strand(ioc))
            , stream_(net::make_strand(ioc))

        {
        }
        //void run(char const*, char const*, char const*, int,float);

        void sendData(char const*, char const*, char const*, int);

        void on_resolve(beast::error_code, tcp::resolver::results_type);
        void on_connect(beast::error_code, tcp::resolver::results_type::endpoint_type);
        void on_write(beast::error_code, std::size_t);
        void on_read(beast::error_code, std::size_t);
};

void Client::sendData(char const* host, char const* port, char const* target, int version) {

    req_.version(version);
    spdlog::info("running");
    req_.method(http::verb::post);
    req_.target(target);
    req_.set(http::field::host, host);
    req_.set(boost::beast::http::field::user_agent, BOOST_BEAST_VERSION_STRING);
    req_.set(http::field::accept, "*/*");

    req_.set(http::field::content_type, "application/json");

    bj::value data = {
        {"dia", randomFloat(2.3,2.5)},
        {"inner",randomFloat(2.2,2.4)},
        {"core",randomFloat(2.0,2.2)},
        {"sleep_time_in_s", 0.01}
    };

    req_.body() = bj::serialize(data);
    req_.prepare_payload();

    resolver_.async_resolve(
        host,
        port,
        beast::bind_front_handler(
            &Client::on_resolve,
            shared_from_this()));
}

void Client::on_resolve(beast::error_code ec, tcp::resolver::results_type results)
{
    
        if (ec)
            return fail(ec, "resolve");

        stream_.expires_after(std::chrono::milliseconds(10000));

        // Make the connection on the IP address we get from a lookup
        stream_.async_connect(
            results,
            beast::bind_front_handler(
                &Client::on_connect,
                shared_from_this()));
   
}


void Client::on_connect(beast::error_code ec, tcp::resolver::results_type::endpoint_type)
{
        if (ec)
            return fail(ec, "connect");

        // Set a timeout on the operation
        stream_.expires_after(std::chrono::milliseconds(1000));
        std::size_t bytes_transferred;

        // Send the HTTP request to the remote host
        http::async_write(stream_, req_,
            beast::bind_front_handler(
                &Client::on_write,
                shared_from_this()));         
}

void Client::on_write(beast::error_code ec, std::size_t bytes_transferred) {

    if (ec)
        return fail(ec, "write");


     //Receive the HTTP response
    http::async_read(stream_, buffer_, res_,
        beast::bind_front_handler(
            &Client::on_read,
            shared_from_this()));
}

void Client::on_read(beast::error_code ec, std::size_t bytes_transferred)
{
    boost::ignore_unused(bytes_transferred);

    if (ec)
        return fail(ec, "read");

    std::cout<<"Response of client :"<< res_ <<std::endl;
}

int main() {
    net::io_context ioc;
    char* m_host = "127.0.0.1";
    char* m_port = "28";
    char* target = "/metrics/";
    int m_version = 1;
    //Launch the asynchronous operation
    std::make_shared<Client>(ioc)->sendData(m_host, m_port, target, m_version);
    ioc.run();

}

我用数据将数据从客户端发送到服务器。

我尝试使用客户端中的线程将连续数据从客户端发送到服务器,但出现 Abort 错误。

我在 on_connect 方法上尝试了线程,并且每次都会像下面的代码一样添加数据。

我当时在 sendData 函数上尝试了线程,也出现了 Abort 错误。

**如果我想从客户端向服务器发送连续数据,有什么方法。

**发送数据后关闭客户端并再次连接服务器,可以吗?

**不关闭服务器从客户端到服务器的连续发布请求数据?

bj::value data = {
        {"dia", randomFloat(2.3,2.5)},
        {"inner",randomFloat(2.2,2.4)},
        {"core",randomFloat(2.0,2.2)},
        {"sleep_time_in_s", 0.01}
    };

    req_.body() = bj::serialize(data);

回答1

因此,您的代码不完整,包含大量不需要的依赖项,并且没有显示您要执行的操作。

这是自包含的代码,请从这里开始并保持自包含以说明您遇到的问题。

http://coliru.stacked-crooked.com/a/15e11af9c5794033

#include <boost/algorithm/string.hpp>
#include <boost/asio.hpp>
#include <boost/beast.hpp>

#include <boost/json.hpp>
#include <boost/json/src.hpp>

//#include <Windows.h>

//#include <opencv2/calib3d/calib3d.hpp>
//#include <opencv2/highgui/highgui.hpp>
//#include <opencv2/imgproc/imgproc.hpp>
//#include <opencv2/opencv.hpp>
//

#include <random>
#include <iostream>
namespace spdlog {
    void info(auto&&...) {}
} // namespace spdlog

static double randomFloat(double min, double max) {
    static std::mt19937 prng;
    return std::uniform_real_distribution<double>(min, max)(prng);
}

namespace beast = boost::beast;         // from <boost/beast.hpp>
namespace http  = beast::http;          // from <boost/beast/http.hpp>
namespace net   = boost::asio;          // from <boost/asio.hpp>
using tcp       = boost::asio::ip::tcp; // from <boost/asio/ip/tcp.hpp>
namespace bj    = boost::json;
using boost::asio::steady_timer;

static void fail(beast::error_code ec, std::string_view what) {
    std::cerr << ec.message() << ": " << what << std::endl;
    exit(1);
}

class Client : public std::enable_shared_from_this<Client> {
    tcp::resolver                     resolver_;
    beast::tcp_stream                 stream_;
    beast::flat_buffer                buffer_; // (Must persist between reads)
    http::request<http::string_body>  req_;
    http::response<http::string_body> res_;
    int                               m_outer;

  public:
    // Objects are constructed with a strand to
    // ensure that handlers do not execute concurrently.
    explicit Client(net::io_context& ioc)
        : resolver_(net::make_strand(ioc))
        , stream_(net::make_strand(ioc))

    {}
    // void run(char const*, char const*, char const*, int,float);

    void sendData(char const*, char const*, char const*, int);

  private:
    void on_resolve(beast::error_code, tcp::resolver::results_type);
    void on_connect(beast::error_code, tcp::resolver::results_type::endpoint_type);
    void on_write(beast::error_code, std::size_t);
    void on_read(beast::error_code, std::size_t);
};

void Client::sendData(char const* host, char const* port, char const* target,
                      int version) {

    req_.version(version);
    spdlog::info("running");
    req_.method(http::verb::post);
    req_.target(target);
    req_.set(http::field::host, host);
    req_.set(boost::beast::http::field::user_agent, BOOST_BEAST_VERSION_STRING);
    req_.set(http::field::accept, "*/*");

    req_.set(http::field::content_type, "application/json");

    bj::value data = {{"dia", randomFloat(2.3, 2.5)},
                      {"inner", randomFloat(2.2, 2.4)},
                      {"core", randomFloat(2.0, 2.2)},
                      {"sleep_time_in_s", 0.01}};

    req_.body() = bj::serialize(data);
    req_.prepare_payload();

    resolver_.async_resolve(
        host, port, beast::bind_front_handler(&Client::on_resolve, shared_from_this()));
}

void Client::on_resolve(beast::error_code ec, tcp::resolver::results_type results) {

    if (ec)
        return fail(ec, "resolve");

    stream_.expires_after(std::chrono::milliseconds(10000));

    // Make the connection on the IP address we get from a lookup
    stream_.async_connect(
        results, beast::bind_front_handler(&Client::on_connect, shared_from_this()));
}

void Client::on_connect(beast::error_code ec,
                        tcp::resolver::results_type::endpoint_type) {
    if (ec)
        return fail(ec, "connect");

    // Set a timeout on the operation
    stream_.expires_after(std::chrono::milliseconds(1000));

    // Send the HTTP request to the remote host
    http::async_write(stream_, req_,
                      beast::bind_front_handler(&Client::on_write, shared_from_this()));
}

void Client::on_write(beast::error_code ec, std::size_t bytes_transferred) {
    boost::ignore_unused(bytes_transferred);

    if (ec)
        return fail(ec, "write");

    // Receive the HTTP response
    http::async_read(stream_, buffer_, res_,
                     beast::bind_front_handler(&Client::on_read, shared_from_this()));
}

void Client::on_read(beast::error_code ec, std::size_t bytes_transferred) {
    boost::ignore_unused(bytes_transferred);

    if (ec)
        return fail(ec, "read");

    std::cout << "Response of client :" << res_ << std::endl;
}

int main() {
    net::io_context ioc;
    //std::make_shared<Client>(ioc)->sendData("127.0.0.1", "28", "/metrics", 1);
    // example.com
    std::make_shared<Client>(ioc)->sendData("93.184.216.34", "80", "/metrics", 11);
    ioc.run_for(std::chrono::seconds(3));
}

为了好玩,这里有一个小改动,让它不断重复请求:

http://coliru.stacked-crooked.com/a/385df337cb56354c

#include <boost/algorithm/string.hpp>
#include <boost/asio.hpp>
#include <boost/beast.hpp>

#include <boost/json.hpp>
#include <boost/json/src.hpp>

//#include <Windows.h>

//#include <opencv2/calib3d/calib3d.hpp>
//#include <opencv2/highgui/highgui.hpp>
//#include <opencv2/imgproc/imgproc.hpp>
//#include <opencv2/opencv.hpp>
//

#include <random>
#include <iostream>
namespace spdlog {
    void info(auto&&...) {}
} // namespace spdlog

static double randomFloat(double min, double max) {
    static std::mt19937 prng;
    return std::uniform_real_distribution<double>(min, max)(prng);
}

namespace beast = boost::beast;         // from <boost/beast.hpp>
namespace http  = beast::http;          // from <boost/beast/http.hpp>
namespace net   = boost::asio;          // from <boost/asio.hpp>
using tcp       = boost::asio::ip::tcp; // from <boost/asio/ip/tcp.hpp>
namespace bj    = boost::json;
using boost::asio::steady_timer;

static void fail(beast::error_code ec, std::string_view what) {
    std::cerr << ec.message() << ": " << what << std::endl;
    exit(1);
}

class Client : public std::enable_shared_from_this<Client> {
    tcp::resolver                     resolver_;
    beast::tcp_stream                 stream_;
    beast::flat_buffer                buffer_; // (Must persist between reads)
    http::request<http::string_body>  req_;
    http::response<http::string_body> res_;
    int                               m_outer;

  public:
    // Objects are constructed with a strand to
    // ensure that handlers do not execute concurrently.
    explicit Client(net::io_context& ioc)
        : resolver_(net::make_strand(ioc))
        , stream_(net::make_strand(ioc))

    {}
    // void run(char const*, char const*, char const*, int,float);

    void sendData(char const*, char const*, char const*, int);

  private:
    void on_resolve(beast::error_code, tcp::resolver::results_type);
    void on_connect(beast::error_code, tcp::resolver::results_type::endpoint_type);
    void do_write();
    void on_write(beast::error_code, std::size_t);
    void on_read(beast::error_code, std::size_t);
};

void Client::sendData(char const* host, char const* port, char const* target,
                      int version) {

    req_.version(version);
    spdlog::info("running");
    req_.method(http::verb::post);
    req_.target(target);
    req_.set(http::field::host, host);
    req_.set(boost::beast::http::field::user_agent, BOOST_BEAST_VERSION_STRING);
    req_.set(http::field::accept, "*/*");

    req_.set(http::field::content_type, "application/json");

    bj::value data = {{"dia", randomFloat(2.3, 2.5)},
                      {"inner", randomFloat(2.2, 2.4)},
                      {"core", randomFloat(2.0, 2.2)},
                      {"sleep_time_in_s", 0.01}};

    req_.body() = bj::serialize(data);
    req_.prepare_payload();

    resolver_.async_resolve(
        host, port, beast::bind_front_handler(&Client::on_resolve, shared_from_this()));
}

void Client::on_resolve(beast::error_code ec, tcp::resolver::results_type results) {

    if (ec)
        return fail(ec, "resolve");

    stream_.expires_after(std::chrono::milliseconds(10000));

    // Make the connection on the IP address we get from a lookup
    stream_.async_connect(
        results, beast::bind_front_handler(&Client::on_connect, shared_from_this()));
}

void Client::on_connect(beast::error_code ec,
                        tcp::resolver::results_type::endpoint_type) {
    if (ec)
        return fail(ec, "connect");

    do_write();
}

void Client::do_write() {
    std::cout << " ===== do_write ====== " << std::endl;
    // Set a timeout on the operation
    stream_.expires_after(std::chrono::milliseconds(1000));

    // Send the HTTP request to the remote host
    http::async_write(stream_, req_,
                      beast::bind_front_handler(&Client::on_write, shared_from_this()));
}

void Client::on_write(beast::error_code ec, std::size_t bytes_transferred) {
    boost::ignore_unused(bytes_transferred);

    if (ec)
        return fail(ec, "write");

    // Receive the HTTP response
    http::async_read(stream_, buffer_, res_,
                     beast::bind_front_handler(&Client::on_read, shared_from_this()));
}

void Client::on_read(beast::error_code ec, std::size_t bytes_transferred) {
    boost::ignore_unused(bytes_transferred);

    if (ec)
        return fail(ec, "read");

    std::cout << "Response of client :" << res_ << std::endl;

    do_write();
}

int main() {
    net::io_context ioc;
    //std::make_shared<Client>(ioc)->sendData("127.0.0.1", "28", "/metrics", 1);
    // example.com
    std::make_shared<Client>(ioc)->sendData("93.184.216.34", "80", "/metrics", 11);
    ioc.run_for(std::chrono::seconds(3));
}

在我的系统上:

===== do_write ====== 
Response of client :HTTP/1.1 404 Not Found
Content-Type: text/html
Date: Wed, 18 May 2022 19:04:58 GMT
Server: ECS (bsa/EB19)
Content-Length: 345

<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
         "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
    <head>
        <title>404 - Not Found</title>
    </head>
    <body>
        <h1>404 - Not Found</h1>
    </body>
</html>

 ===== do_write ====== 
Response of client :HTTP/1.1 404 Not Found
Content-Type: text/html
Date: Wed, 18 May 2022 19:04:58 GMT
Server: ECS (bsa/EB19)
Content-Length: 345

<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
         "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
    <head>
        <title>404 - Not Found</title>
    </head>
    <body>
        <h1>404 - Not Found</h1>
    </body>
</html>
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
         "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
    <head>
        <title>404 - Not Found</title>
    </head>
    <body>
        <h1>404 - Not Found</h1>
    </body>
</html>

 ===== do_write ====== 
Response of client :HTTP/1.1 404 Not Found
Content-Type: text/html
Date: Wed, 18 May 2022 19:04:58 GMT
Server: ECS (bsa/EB19)
Content-Length: 345

<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
         "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
...

相似文章