将tornado客户端的http请求发送到异步cpp-netlib服务器

时间:2013-12-19 16:15:56

标签: c++ python http tornado cpp-netlib

我有一个http客户端,我在龙卷风框架中用python编写:

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;
};

但是请求正文总是空的而不是我发回的响应(“你好世界”),大多数时候我得到这样的东西(数字可能不同)

  

错误:HTTP 0:未知

你能告诉我为什么身体是空的,或者为什么反应无法到达?

修改

为什么身体是空的答案。我没有收到响应的错误是:我在服务器中设置连接头后设置了连接状态。只是交换了他们的订单,它就像一个魅力。

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");

1 个答案:

答案 0 :(得分:3)

使用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更改为更高的值,以便您可以避免多次上下文切换。目前无法配置。