MST

星途 面试题库

面试题:网络编程之Boost.Asio基础应用

在Boost.Asio中,简述如何创建一个简单的TCP服务器,用于接收客户端连接并回显客户端发送的数据,请写出关键代码片段并解释其原理。
18.1万 热度难度
后端开发网络编程

知识考点

AI 面试

面试题答案

一键面试
  1. 关键代码片段
#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;
}
  1. 原理解释
    • 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 的性能,提高服务器的并发处理能力。最后等待所有线程结束。