面试题答案
一键面试- 引入必要的头文件:
#include <iostream>
#include <boost/asio.hpp>
这部分代码引入了标准输入输出流头文件和Boost.Asio库的头文件,boost/asio.hpp
包含了Asio库常用的功能。
- 定义处理客户端连接的类:
class session : public std::enable_shared_from_this<session> {
public:
session(boost::asio::io_context& io_context) : socket_(io_context) {}
boost::asio::ip::tcp::socket& socket() {
return socket_;
}
void start() {
do_read();
}
private:
void do_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 data;
std::istream is(&buffer_);
std::getline(is, data);
std::cout << "Received: " << data << std::endl;
do_write(data);
}
});
}
void do_write(const std::string& data) {
auto self(shared_from_this());
boost::asio::async_write(socket_, boost::asio::buffer(data + "\n"),
[this, self](boost::system::error_code ec, std::size_t /*length*/) {
if (!ec) {
do_read();
}
});
}
boost::asio::ip::tcp::socket socket_;
boost::asio::streambuf buffer_;
};
- `session`类继承自`std::enable_shared_from_this`,以便能够安全地使用`shared_from_this`来获取自身的`std::shared_ptr`。
- 构造函数接受一个`boost::asio::io_context&`,用于创建与客户端通信的`socket_`。
- `socket`函数返回与客户端连接的`socket`。
- `start`函数启动对客户端数据的读取。
- `do_read`函数使用`async_read_until`异步读取客户端数据,直到遇到换行符`'\n'`。读取成功后,将数据打印并调用`do_write`回显数据。
- `do_write`函数使用`async_write`异步将数据写回客户端,写完后再次调用`do_read`准备读取下一次数据。
3. 定义TCP服务器类:
class server {
public:
server(boost::asio::io_context& io_context, unsigned short port) : acceptor_(io_context, boost::asio::ip::tcp::endpoint(boost::asio::ip::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();
});
}
boost::asio::ip::tcp::acceptor acceptor_;
boost::asio::ip::tcp::socket socket_;
};
- `server`类的构造函数接受`boost::asio::io_context&`和端口号`port`,创建一个`acceptor_`来监听指定端口,并初始化一个`socket_`。
- `do_accept`函数使用`async_accept`异步接受客户端连接。接受成功后,创建一个`session`对象来处理该客户端连接,并启动`session`的读取操作。然后再次调用`do_accept`准备接受下一个客户端连接。
4. 主函数:
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;
}
- 在`main`函数中,创建一个`io_context`对象和一个`server`对象,监听端口`12345`。
- 创建多个线程来运行`io_context`,线程数量根据系统的CPU核心数确定,以充分利用多核资源。
- 最后等待所有线程执行完毕。如果捕获到异常,打印异常信息。