#include <sys/types.h>
#include <sys/wait.h>
#include <iostream>
#include <string>
#include <array>
#include <boost/asio.hpp>
class server {
public:
server(boost::asio::io_service &ios, unsigned short port) : ios_(ios), acceptor_(ios_, {boost::asio::ip::tcp::v4(), port}), socket_(ios_), signal_(ios_, SIGCHLD) {
wait_for_signal();
accept();
}
private:
void wait_for_signal() {
signal_.async_wait([this] (boost::system::error_code, int) { // 当lamba函数返回true 则调用 后面在需要调用wait_for_signal()继续执行
if (true == acceptor_.is_open()) { // parent process
std::cout << "start to wait child process." << std::endl;
int status = 0;
while (waitpid(-1, &status, WNOHANG) > 0) {
}
wait_for_signal();
}
});
}
void accept() {
acceptor_.async_accept([this] (boost::system::error_code ec, boost::asio::ip::tcp::socket new_socket) {
if (ec) {
std::cerr << "accpetor error:" << ec.message() << std::endl;
accept();
return;
}
socket_ = std::move(new_socket);
ios_.notify_fork(boost::asio::io_service::fork_prepare);
int pid = fork();
if (0 == pid) {
std::cout << "fork a sub process to go." << std::endl;
ios_.notify_fork(boost::asio::io_service::fork_child);
acceptor_.close();
signal_.cancel();
read();
}
if (pid > 0) {
std::cout << "parent process to close socket and reaccept." << std::endl;
ios_.notify_fork(boost::asio::io_service::fork_parent);
socket_.close();
accept();
}
});
}
void read() {
socket_.async_read_some(boost::asio::buffer(data_), [this] (boost::system::error_code ec, size_t length) {
if (!ec) {
std::cout << "server read data." << std::endl;
write(length);
}
});
}
void write(size_t length) {
boost::asio::async_write(socket_, boost::asio::buffer(data_, length), [this] (boost::system::error_code ec, size_t length) {
if (!ec) {
read();
}
});
}
private:
static constexpr size_t BUFF_SIZE = 1024;
private:
std::array<char, BUFF_SIZE>data_;
boost::asio::io_service &ios_;
boost::asio::signal_set signal_;
boost::asio::ip::tcp::acceptor acceptor_;
boost::asio::ip::tcp::socket socket_;
};
int main(int argc, const char **argv) {
if (2 != argc) {
std::cerr << "usage ./programe port." << std::endl;
return -1;
}
boost::asio::io_service ios;
try {
server my_server(ios, atoi(argv[1]));
ios.run();
}
catch (std::exception &e) {
std::cerr << e.what() << std::endl;
}
return 0;
}