我有一个我在 Tornado 框架中用python写的http客户端:

http_client = httpclient.HTTPClient()
request = httpclient.HTTPRequest("http://127.0.0.1:8000", method='PUT', body=str("data"))
response = http_client.fetch(request)

另一方面,我有一台异步服务器,该服务器是使用cpp-netlib在c++中编写的。它基本上必须阅读请求并打印其主体

class Server;
typedef http::async_server<Server> server;

class Server {
public:
void operator()(server::request const & request, server::connection_ptr connection)
{
    boost::shared_ptr<connection_handler> h(new connection_handler());
    (*h)(request, connection);

    server::response_header headers[] = { {"Connection","close"} ,{"Content-Type", "text/plain"} };
    connection->set_headers(boost::make_iterator_range(headers, headers+2));
    connection->set_status(server::connection::accepted);
    connection->write("helloworld");
}

int main()
{
    Server handler;
    server::options options(handler);
    server instance(
    options.thread_pool(boost::make_shared<utils::thread_pool>(5))
           .address("0.0.0.0")
           .port("8000"));

    instance.run();
    return 0;
}

连接处理程序如下所示:

struct connection_handler : boost::enable_shared_from_this<connection_handler>
{

    struct read_post_callback
    {
        typedef boost::shared_ptr<connection_handler> handler_ptr_t;
        read_post_callback(handler_ptr_t  handler_ptr) : handler(handler_ptr) {}

        void operator()(server::connection::input_range range, boost::system::error_code error, size_t size, server::connection_ptr conn)
        {
            handler->read_sofar += size;
            handler->cond.notify_one();
        }

        handler_ptr_t handler;
    };

    void operator()(server::request const &req, server::connection_ptr conn)
    {
        int cl;
        server::request::headers_container_type const &hs = req.headers;
        for(server::request::headers_container_type::const_iterator it = hs.begin(); it!=hs.end(); ++it)
        {
            if(boost::to_lower_copy(it->name)=="content-length")
            {
                cl = boost::lexical_cast<int>(it->value);
                break;
            }
        }
        cout<< req.body << endl;
        read_sofar = 0;
        while(read_sofar<cl)
        {
            boost::unique_lock<boost::mutex> lock(mtx);
            server::connection::read_callback_function cc = read_post_callback(shared_from_this());
            conn->read(cc);

            cond.wait(lock);
        }
    }

    int read_sofar;
    boost::condition_variable cond;
    boost::mutex mtx;
};

但是,请求正文始终为空,大多数情况下,我收到的不是我发回的响应(“hello world”)(数字可能不同)



你能告诉我为什么 body 是空的或者为什么没有反应吗?

编辑:

为什么 body 空着才是答案。我做错了,我没有收到响应,这是这样的:我在服务器中设置了连接头后,就设置了连接状态。只需交换他们的订单,它就像一个魅力。
server::response_header headers[] = { {"Connection","close"} ,{"Content-Type", "text/plain"} };

connection->set_status(server::connection::accepted);
connection->set_headers(boost::make_iterator_range(headers, headers+2));
connection->write("helloworld");

最佳答案

使用cpp-netlib,异步读取必须按如下方式进行。 req.body不会加载从异步读取的数据。因此,必须拥有自己的数据持有人。

struct connection_handler : boost::enable_shared_from_this<connection_handler>
{
        std::string                 body;
        boost::condition_variable   cond;
        boost::mutex                mtx;
        size_t                      read_sofar;

        connection_handler(const server::request& req, const server::connection_ptr& conn) :
                conn(conn),
                body("")
        {
        }

        ~connection_handler()
        {
        }

        void operator()(const server::request& req, const server::connection_ptr& conn)
        {
                size_t cl = 0;
                auto const& hs = req.headers;
                for (auto it = hs.begin(); it != hs.end(); ++it)
                {
                        if (boost::to_lower_copy(it->name)=="content-length")
                        {
                                cl = boost::lexical_cast<size_t>(it->value);
                                break;
                        }
                }

                read_sofar = 0;
                while (read_sofar < cl)
                {
                        boost::unique_lock<boost::mutex> lock(mtx);
                        read_chunk(cl - read_sofar, conn);

                        LogTrace(("gonna wait"));
                        cond.wait(lock);
                        LogTrace(("wokeup"));
                }
        }

        void read_chunk(size_t left2read, server::connection_ptr conn)
        {
                LogTrace(("left2read: %ld", left2read));
                conn->read(
                           boost::bind(
                                       &connection_handler::handle_post_read,
                                       connection_handler::shared_from_this(),
                                       _1, _2, _3, conn, left2read
                                      )
                          );
        }

        void handle_post_read(server::connection::input_range range,
                              boost::system::error_code error,
                              size_t size,
                              server::connection_ptr conn,
                              size_t left2read)
        {
                if (!error)
                {
                        LogTrace(("readSize: %ld", size));
                        body.append(boost::begin(range), size);
                        size_t left = left2read - size;
                        read_sofar += size;
                        if (left > 0)
                        {
                                read_chunk(left, conn);
                        }
                        else
                        {
                                cond.notify_one();
                        }
                }
                LogTrace((error.message()));
        }
};

另外,您可能需要将BOOST_NETWORK_HTTP_SERVER_CONNECTION_BUFFER_SIZE中定义的boost/network/protocol/http/serversync_connection.hpp更改为更高的值,以便避免进行多个上下文切换。目前无法配置。

关于c++ - 从 Tornado 客户端发送HTTP请求到异步cpp-netlib服务器,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/20686507/

10-11 22:59
查看更多