使用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

目录
相关文章
|
4月前
|
网络协议 Linux
Linux查看端口监听情况,以及Linux查看某个端口对应的进程号和程序
Linux查看端口监听情况,以及Linux查看某个端口对应的进程号和程序
721 2
|
2月前
|
运维 Linux
Linux查找占用的端口,并杀死进程的简单方法
通过上述步骤和命令,您能够迅速识别并根据实际情况管理Linux系统中占用特定端口的进程。为了获得更全面的服务器管理技巧和解决方案,提供了丰富的资源和专业服务,是您提升运维技能的理想选择。
85 1
|
2月前
通过进程识别号查看SQLserve端口号
通过进程识别号查看SQLserve端口号
43 0
|
4月前
|
网络协议
Mac根据端口查询进程id的命令
这篇文章介绍了在Mac操作系统上如何使用两种命令来查询监听特定端口的进程ID。第一种方法是使用`netstat -anp tcp -v | grep 端口号`,例如`netstat -anp tcp -v | grep 80`,这将列出所有使用端口80的TCP连接及其相关信息。第二种方法是使用`lsof -P -n -i:端口号`,例如`lsof -P -n -i:8080`,这将显示使用指定端口的进程列表,包括进程ID、用户、文件描述符等信息。文章通过示例展示了如何使用这些命令,并提供了输出结果的截图。
367 2
|
4月前
|
Windows
Windows中如何查看被占用的端口、杀掉对应的进程
这篇文章介绍了在Windows系统中如何查看被占用的端口号以及如何杀掉占用端口的进程,包括使用命令提示符的`netstat -ano | findstr 端口号`命令查找进程PID,然后通过任务管理器或`taskkill /PID PID号`命令来结束进程。
Windows中如何查看被占用的端口、杀掉对应的进程
|
4月前
|
存储 安全 Python
[python]使用标准库logging实现多进程安全的日志模块
[python]使用标准库logging实现多进程安全的日志模块
|
4月前
|
开发框架 .NET Linux
【Azure 应用服务】 部署到App Service for Linux 服务的Docker 镜像,如何配置监听端口呢?
【Azure 应用服务】 部署到App Service for Linux 服务的Docker 镜像,如何配置监听端口呢?
|
4月前
|
网络协议
【qt】TCP的监听 (设置服务器IP地址和端口号)
【qt】TCP的监听 (设置服务器IP地址和端口号)
272 0
|
4月前
|
Linux Windows
Windows查找监听端口对应的进程及其路径
Windows查找监听端口对应的进程及其路径
129 0
|
5月前
|
运维 关系型数据库 MySQL
掌握taskset:优化你的Linux进程,提升系统性能
在多核处理器成为现代计算标准的今天,运维人员和性能调优人员面临着如何有效利用这些处理能力的挑战。优化进程运行的位置不仅可以提高性能,还能更好地管理和分配系统资源。 其中,taskset命令是一个强大的工具,它允许管理员将进程绑定到特定的CPU核心,减少上下文切换的开销,从而提升整体效率。
掌握taskset:优化你的Linux进程,提升系统性能