class session_http {
public:
session_http(boost::asio::io_context &io) : socket_(io) {};
void run(boost::asio::yield_context yield) {
boost::system::error_code ec;
boost::beast::flat_buffer buffer;
while (true) {
// Read a request
boost::beast::http::async_read(socket_, buffer, req_, yield[ec]);
if(ec) {
BOOST_LOG_TRIVIAL(error) << "Read fail: " << ec.message();
break;
}
BOOST_LOG_TRIVIAL(debug) << "Read: " << req_;
BOOST_LOG_TRIVIAL(info) << "Read: " << req_.method_string() << " " << req_.target();
send_response(yield, "success");
if(req_.need_eof()) {// ture means Connection: close
// This means we should close the connection, usually because
// the response indicated the "Connection: close" semantic.
break;
}
req_.body().clear();
}
// Send a TCP shutdown
socket_.shutdown(boost::asio::ip::tcp::socket::shutdown_send, ec);
}
private:
void send_response(boost::asio::yield_context yield, const std::string &body) {
boost::system::error_code ec;
// Send the response
boost::beast::http::response<boost::beast::http::string_body>
res{boost::beast::http::status::ok, req_.version()};
res.set(boost::beast::http::field::server, "Server");
res.set(boost::beast::http::field::content_type, "text/json");
res.body() = body;
res.content_length(body.length());
res.keep_alive(req_.keep_alive());
BOOST_LOG_TRIVIAL(debug) << "Write: " << res;
BOOST_LOG_TRIVIAL(info) << "Write: " << res.result_int() << " " << body.length() << " " << res.body();
boost::beast::http::async_write(socket_, res, yield[ec]);
if(ec) {
BOOST_LOG_TRIVIAL(error) << "Write fail: " << ec.message();
}
}
boost::asio::ip::tcp::socket socket_;
boost::beast::http::request<boost::beast::http::string_body> req_;
friend class server_http;
};
class server_http {
public:
server_http(boost::asio::io_context &io) : acceptor_(io) {};
void init() {
boost::system::error_code ec;
boost::asio::ip::tcp::endpoint addr(boost::asio::ip::tcp::v6(), 8888);
acceptor_.open(addr.protocol());
acceptor_.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true), ec);
acceptor_.bind(addr);
acceptor_.listen(2048);
};
void run(boost::asio::yield_context yield) {
boost::system::error_code ec;
while (true) {
auto session = std::make_shared<session_http>(acceptor_.get_executor().context());
acceptor_.async_accept(session->socket_, yield[ec]);
if (ec) {
BOOST_LOG_TRIVIAL(error) << "Accep error: " << ec.message();
continue;
}
BOOST_LOG_TRIVIAL(debug) << "Accep request " << session->socket_.remote_endpoint(ec);
if (ec) {
BOOST_LOG_TRIVIAL(error) << "remote_endpoint http error: " << ec.message();
continue;
}
// 在單獨的協程當中運作 session
boost::asio::spawn(acceptor_.get_executor(), std::bind(&session_http::run, session, std::placeholders::_1));
}
};
boost::asio::ip::tcp::acceptor acceptor_;
private:
};
void run(boost::asio::io_context& io);
#include<sys/types.h>
#include<sys/wait.h>
int main(int argc, char* argv[]) {
// 基礎的運作上下文
boost::asio::io_context io;
// http服務
server_http http(io);
http.init();
// boost::asio::spawn(io, std::bind(&server_http::run, &http, std::placeholders::_1));
pid_t p;
for (int i = 0; i < 4; i++) {
p = fork();
//子程序退出循環,不再建立子程序,全部由主程序建立子程序,這裡是關鍵所在
if (p==0 || p==-1) {
break;
}
}
if (p == -1) {
std::cout << "fail to fork!" << std::endl;
return 0;
} else if (p == 0) {
//子程序處理邏輯
// 基礎的運作上下文
boost::asio::io_context io;
server_http http_child(io);
boost::asio::ip::tcp::endpoint addr(boost::asio::ip::tcp::v6(), 8888);
http_child.acceptor_.assign(addr.protocol(), http.acceptor_.native_handle() );
boost::asio::spawn(io, std::bind(&server_http::run, &http_child, std::placeholders::_1));
std::cout << "child:" << getpid() << std::endl;
std::vector<std::thread> v;
for(auto i = 4; i > 0; --i) {
v.emplace_back([&] {run(std::ref(io));});
}
for(int i=0;i<4;++i) {
v[i].join();
}
} else {
// 父程序
std::cout << "main:" << getpid() << std::endl;
waitpid(p, NULL, 0);
}
}
void run(boost::asio::io_context& io) {
io.run();
}
多個程序共同監聽同一端口,效率和同一個程序用協程方式處理一樣,多程序并沒有提高tps