使用boost::asio库实现多个子进程监听同一个端口

简介: class session_http {public: session_http(boost::asio::io_context &io) : socket_(io) {}; void run(boost::asi...
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

目录
相关文章
|
2月前
|
负载均衡 网络协议 算法
slb监听协议与端口
SLB是云服务商提供的负载均衡服务,用于分发客户端请求到多台后端服务器,提升服务可用性和响应速度。关键概念包括监听协议(TCP、UDP、HTTP、HTTPS、TCPSSL)和监听端口。监听协议决定了SLB处理请求的方式,而监听端口则是SLB接收请求的入口。配置时需根据应用选择合适协议和端口,并可设置负载均衡算法(如轮询、最少连接等)。客户端应通过SLB统一入口访问后端服务,避免绕过SLB导致的问题。
73 2
|
2月前
|
负载均衡 网络协议 安全
slb选择监听协议和端口
阿里云SLB中,监听协议(TCP、HTTP、HTTPS)与端口(80、443等)决定客户端请求的处理方式。TCP适用于纯TCP或自处理HTTP的场景,HTTP用于智能调度Web服务,HTTPS提供安全的HTTP传输。监听端口通常匹配应用标准,如80 for HTTP,443 for HTTPS。配置时,可考虑HTTPS重定向和传递`X-Forwarded-Proto`头以识别请求来源。选择应基于业务需求和安全考虑。
42 3
|
4月前
|
Windows
windows环境下根据端口号查询进程编号并杀掉此进程
windows环境下根据端口号查询进程编号并杀掉此进程
|
6月前
|
Windows
Windows查看端口占用以及关闭相应的进程
Windows查看端口占用以及关闭相应的进程
145 0
|
1月前
|
Linux Apache
CentOS 7 源码安装LAMP环境源 和apache监听别的端口
CentOS 7 源码安装LAMP环境源 和apache监听别的端口
21 0
|
2月前
|
前端开发 Android开发 iOS开发
应用研发平台EMAS使用 aliyun-react-native-push 库接入推送和辅助通道,推送都可以收到,但是在App切到后台或者杀掉进程之后就收不到推送了,是需要配置什么吗?
【2月更文挑战第31天】应用研发平台EMAS使用 aliyun-react-native-push 库接入推送和辅助通道,推送都可以收到,但是在App切到后台或者杀掉进程之后就收不到推送了,是需要配置什么吗?
32 2
|
3月前
window查看端口占用并关闭对应进程
window查看端口占用并关闭对应进程
|
7月前
|
Windows
windows系统 如何查看端口占用情况并关闭占用的进程?
windows系统 如何查看端口占用情况并关闭占用的进程?
225 0
|
4月前
|
运维 安全 数据库
cmd中使用telnet检测远程的ip及端口是否处于监听状态
cmd中使用telnet检测远程的ip及端口是否处于监听状态
33 1
|
4月前
|
Linux
遇到Linux 端口占用时如何查看并杀掉服务进程
遇到Linux 端口占用时如何查看并杀掉服务进程