cpp-netlib:参考:1. http://cpp-netlib.org/
2.
https://github.com/cpp-netlib/3.
http://github.com/cpp-netlib/解析版本: cpp-netlib-0.9.4注:使用的boost版本为boost_1_53_0。 若使用boost_1_46_1在Windows上编译会出现错误。
测试代码testAsyncServer.cpp
#include "CommonPrecomp.h"
#include "RequestHandler.h"
#include "RequestHandlerFactory.h"
#include <string>
#include <iostream>
struct test_handler {
/* when there are many request at the same time, can put the request into a queue, then let another thread process it.
* or maybe need to call http::client to connect to other server, and get response.
*/
void operator()(const server::request &request, server::connection_ptr connection)
{
request_handler_ptr request_handler_ = request_handler_factory::get_mutable_instance().create();
return request_handler_->start(request, connection);
}
};
int main(int argc, char* argv[]) {
if (argc != 3) {
std::cerr << "Usage: " << argv[0] << " address port" << std::endl;
return 1;
}
try {
test_handler handler;
utils::thread_pool thread_pool_(2);
server instance(argv[1], argv[2], handler, thread_pool_);
instance.run();
}
catch (std::exception &e) {
std::cerr << e.what() << std::endl;
return 1;
}
return 0;
}
CommonPrecomp.h
#ifndef _COMMON_PRECOMP_H_
#define _COMMON_PRECOMP_H_
#include <boost/shared_ptr.hpp>
#include <boost/network/protocol/http/server.hpp>
#include <boost/range/algorithm/find_if.hpp>
#include <boost/serialization/singleton.hpp>
namespace http = boost::network::http;
namespace utils = boost::network::utils;
struct test_handler;
typedef boost::network::http::async_server<test_handler> server;
#endif // _COMMON_PRECOMP_H_
CommonPrecomp.cpp
#include "CommonPrecomp.h"
RequestHandler.h
#ifndef _REQUEST_HANDLER_H_
#define _REQUEST_HANDLER_H_
class request_handler
{
public:
struct is_content_length {
template <class Header>
bool operator()(Header const & header) {
return boost::iequals(header.name, "content-length");
}
};
request_handler();
~request_handler();
void start(const server::request &request, server::connection_ptr connection);
void read_callback(server::connection::input_range input, boost::system::error_code const & ec, std::size_t bytes_transferred, server::connection_ptr connection);
void write_callback(boost::system::error_code const & ec);
private:
std::string uri_;
std::string content_;
std::size_t content_length_;
std::size_t read_content_length_;
private:
static server::response_header common_headers[3];
static std::string bad_request;
};
typedef boost::shared_ptr<request_handler> request_handler_ptr;
#endif // _REQUEST_HANDLER_H_
RequestHandler.cpp
#include "CommonPrecomp.h"
#include "RequestHandler.h"
#include "RequestHandlerFactory.h"
request_handler::request_handler()
: uri_()
, content_()
, content_length_(0)
, read_content_length_(0)
{
std::cout << "request_handler constructor!" << std::endl;
}
request_handler::~request_handler()
{
std::cout << "request_handler destructor!" << std::endl;
}
void request_handler::start(const server::request &request, server::connection_ptr connection)
{
if (request.method == "POST")
{
server::request::headers_container_type::iterator found =
boost::find_if(request.headers, is_content_length());
if (found == request.headers.end())
{
connection->set_status(server::connection::bad_request);
connection->set_headers(boost::make_iterator_range(common_headers, common_headers+3));
connection->write(bad_request, boost::bind(&request_handler::write_callback, this, _1));
return;
}
uri_ = http::destination(request);
content_length_ = boost::lexical_cast<std::size_t>(found->value);
connection->read(boost::bind(&request_handler::read_callback, this, _1, _2, _3, _4));
return;
}
else
{
connection->set_status(server::connection::bad_request);
connection->set_headers(boost::make_iterator_range(common_headers, common_headers+3));
connection->write(bad_request, boost::bind(&request_handler::write_callback, this, _1));
}
}
void request_handler::read_callback(server::connection::input_range input, boost::system::error_code const & ec, std::size_t bytes_transferred, server::connection_ptr connection)
{
if (ec)
{
std::cerr << "Error: " << ec << std::endl;
// todo others.
return;
}
read_content_length_ += bytes_transferred;
content_ += std::string(input.begin(), input.end());
if (read_content_length_ < content_length_)
{
connection->read(boost::bind(&request_handler::read_callback, this, _1, _2, _3, _4));
return;
}
if ("/videoProcessing/start" == uri_)
{
// todo: decode the body(content) by creating a message of application logic layer
std::string response_body = "<Message Code=\"0000\" Descript=\"OK.\"></Message>";
std::vector<server::response_header> headers(common_headers, common_headers+3);
headers[2].value = boost::lexical_cast<std::string>(response_body.size());
connection->set_status(server::connection::ok);
connection->set_headers(boost::make_iterator_range(headers.begin(), headers.end()));
connection->write(response_body, boost::bind(&request_handler::write_callback, this, _1));
}
else
{
connection->set_status(server::connection::bad_request);
connection->set_headers(boost::make_iterator_range(common_headers, common_headers+3));
connection->write(bad_request, boost::bind(&request_handler::write_callback, this, _1));
}
}
void request_handler::write_callback(boost::system::error_code const & ec)
{
request_handler_factory::get_mutable_instance().destroy(this);
}
server::response_header request_handler::common_headers[3] = {
{"Connection","close"}
,{"Content-Type", "text/plain"}
,{"Content-Length", "0"}
};
std::string request_handler::bad_request("Bad Request.");
RequestHandlerFactory.h
#ifndef _REQUEST_HANDLER_FACTORY_H_
#define _REQUEST_HANDLER_FACTORY_H_
#include "RequestHandler.h"
class request_handler_factory : public boost::serialization::singleton<request_handler_factory>
{
public:
request_handler_ptr create();
void destroy(request_handler* handler);
~request_handler_factory();
private:
std::list<request_handler_ptr> request_handler_lst;
};
#endif // _REQUEST_HANDLER_FACTORY_H_
RequestHandlerFactory.cpp
#include "CommonPrecomp.h"
#include "RequestHandlerFactory.h"
#include "RequestHandler.h"
request_handler_factory::~request_handler_factory()
{
}
request_handler_ptr request_handler_factory::create()
{
request_handler_ptr request_handler_(new request_handler());
request_handler_lst.push_back(request_handler_);
return request_handler_;
}
void request_handler_factory::destroy(request_handler* handler)
{
for (std::list<request_handler_ptr>::iterator iter = request_handler_lst.begin();
iter != request_handler_lst.end(); iter++)
{
if (iter->get() == handler)
{
request_handler_lst.erase(iter);
return;
}
}
}
图1:cppnetlib-asio-async_server.jpg