📜  使用C++ boost :: asio的同步聊天应用程序(1)

📅  最后修改于: 2023-12-03 15:22:18.204000             🧑  作者: Mango

使用C++ boost :: asio的同步聊天应用程序

简介

本篇介绍了一个使用C++ Boost库中的asio库创建基于TCP协议的同步聊天应用程序的方法。

项目需求

我们需要实现一个基于TCP的聊天应用程序,其中:

  • 支持多个聊天客户端连接到服务端,同时可以互相发送消息
  • 服务端负责接受客户端的连接请求,接收客户端发送的消息并将消息广播给其他客户端
  • 客户端可以发送消息,同时接收其他客户端发送的消息
实现过程
1. 定义消息格式

我们需要定义一个消息格式,包括消息头和消息体。

struct Header {
    uint32_t body_size{ 0 };
};

struct Message {
    Header header;
    std::string body;
};
  • 消息头包括消息体的大小
  • 消息体即存放着具体的聊天内容
2. 实现服务端
  • 创建一个io_context对象,用于每个连接的socket
  • 创建一个acceptor对象,用于处理来自客户端的连接请求,并接受连接
  • 对每个客户端创建一个线程,用于接收客户端的消息,并将消息发送给其他客户端
boost::asio::io_context io_context;
boost::asio::ip::tcp::acceptor acceptor(io_context, endpoint);

void session(boost::asio::ip::tcp::socket client_socket) {
    try {
        std::array<char, 8192> buffer{ 0 };
        while (true) {
            boost::system::error_code ec;
            std::size_t length = client_socket.read_some(boost::asio::buffer(buffer), ec);
            if (ec == boost::asio::error::eof) {
                break;
            }
            if (length > 0) {
                Message msg;
                std::memcpy(&msg.header, buffer.data(), sizeof(msg.header));
                msg.body.resize(msg.header.body_size);

                std::memcpy(msg.body.data(), buffer.data() + sizeof(msg.header), msg.header.body_size);
                std::cout << "Received: " << msg.body << std::endl;

                // 将消息发送给其他客户端
                for (auto& session : sessions) {
                    boost::asio::write(session.socket, boost::asio::buffer(buffer, length), ec);
                }
            }
        }
    } catch (std::exception& e) {
        std::cerr << "Exception in thread: " << e.what() << std::endl;
    }
}

注意事项:

  • client_socket用于与客户端通信,处理网络I/O操作
  • 对于每个收到的消息,需要解析出header和body,并打印出来,同时再将消息广播给其他客户端
3. 实现客户端
  • 使用boost::asio::io_context创建一个tcp::socket
  • 连接服务端
  • 在线程中循环读取服务端发送的消息,并将消息打印出来
boost::asio::io_context io_context;
boost::asio::ip::tcp::socket socket(io_context);
boost::asio::ip::tcp::endpoint endpoint(boost::asio::ip::address::from_string(ip), port);

void receive() {
    try {
        std::array<char, 8192> buffer{ 0 };
        while (true) {
            boost::system::error_code ec;
            std::size_t length = socket.read_some(boost::asio::buffer(buffer), ec);
            if (ec == boost::asio::error::eof) {
                break;
            } else if (length > 0) {
                std::string message(buffer.data(), length);
                std::cout << "Received: " << message << std::endl;
            }
        }
    } catch (std::exception& e) {
        std::cerr << "Exception in thread: " << e.what() << std::endl;
    }
}
4. 发送消息

客户端可以通过cin输入消息并发送到服务端

std::string message;
while (std::getline(std::cin, message)) {
    Message msg;
    msg.header.body_size = message.size();
    msg.body = message;

    boost::asio::write(socket, boost::asio::buffer(&msg.header, sizeof(msg.header)));
    boost::asio::write(socket, boost::asio::buffer(msg.body));
}

注意事项:

  • 首先输入消息,并构造消息体
  • 将消息头和消息体分别写入socket中
结语

以上便是使用C++ Boost库中的asio库创建基于TCP协议的同步聊天应用程序的全部内容。

完整代码请参考GitHub

参考资料
  1. Boost.Asio Tutorial