面试题答案
一键面试- 关键代码片段
#include <iostream>
#include <boost/asio.hpp>
using boost::asio::ip::tcp;
class session : public std::enable_shared_from_this<session> {
public:
session(tcp::socket socket) : socket_(std::move(socket)) {}
void start() {
read();
}
private:
void read() {
auto self(shared_from_this());
boost::asio::async_read_until(socket_, buffer_, '\n',
[this, self](boost::system::error_code ec, std::size_t length) {
if (!ec) {
std::string line;
std::istream is(&buffer_);
std::getline(is, line);
std::cout << "Received: " << line << std::endl;
write(line + "\n");
}
});
}
void write(std::string response) {
auto self(shared_from_this());
boost::asio::async_write(socket_, boost::asio::buffer(response),
[this, self](boost::system::error_code ec, std::size_t /*length*/) {
if (!ec) {
read();
}
});
}
tcp::socket socket_;
boost::asio::streambuf buffer_;
};
class server {
public:
server(boost::asio::io_context& io_context, unsigned short port)
: acceptor_(io_context, tcp::endpoint(tcp::v4(), port)),
socket_(io_context) {
do_accept();
}
private:
void do_accept() {
acceptor_.async_accept(socket_,
[this](boost::system::error_code ec) {
if (!ec) {
std::make_shared<session>(std::move(socket_))->start();
}
do_accept();
});
}
tcp::acceptor acceptor_;
tcp::socket socket_;
};
在 main
函数中:
int main() {
try {
boost::asio::io_context io_context;
server s(io_context, 12345);
std::vector<std::thread> threads;
for (std::size_t i = 0; i < std::thread::hardware_concurrency(); ++i) {
threads.emplace_back([&io_context]() { io_context.run(); });
}
for (auto& thread : threads) {
thread.join();
}
} catch (std::exception& e) {
std::cerr << "Exception: " << e.what() << std::endl;
}
return 0;
}
- 原理解释
session
类:- 每个客户端连接都会由一个
session
对象处理。session
类持有一个tcp::socket
实例,用于与客户端进行通信。 start
方法启动读取操作。read
方法使用async_read_until
异步读取数据,直到遇到换行符'\n'
。当数据读取成功后,将数据打印出来,并调用write
方法回显数据。write
方法使用async_write
异步发送数据,发送完成后再次调用read
方法,以继续接收下一条数据。
- 每个客户端连接都会由一个
server
类:server
类负责监听指定端口,接受客户端连接。它持有一个tcp::acceptor
用于监听,以及一个tcp::socket
用于与新连接的客户端进行通信。do_accept
方法使用async_accept
异步接受客户端连接。当有新连接到来时,创建一个session
对象来处理该连接,并递归调用do_accept
以继续监听新的连接。
main
函数:- 创建一个
io_context
对象,用于管理异步操作。 - 创建一个
server
对象,绑定到指定端口并开始监听。 - 根据系统的 CPU 核心数创建多个线程,每个线程运行
io_context.run()
,以处理异步事件。这样可以充分利用多核 CPU 的性能,提高服务器的并发处理能力。最后等待所有线程结束。
- 创建一个