You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Boost Asio异步TCP Socket仅接收单条消息问题求助

问题分析与修复方案

你的服务器代码存在两个关键问题导致无法正确接收第二条消息:

  1. 缓冲区未正确处理:_Data是固定大小的char数组,首次读取后未重置或添加字符串终止符,若后续消息长度小于首次,输出时会包含残留的旧数据,导致你误以为未收到新消息;即使消息长度足够,未手动添加终止符也可能导致输出乱码。

  2. 缺失handle_write实现:Start()方法中绑定了handle_write回调,但代码中未实现该方法,这会导致编译错误或运行时崩溃,间接影响后续读操作的执行。

修复后的完整代码

#include <iostream>
#include <string>
#include <cstring>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/enable_shared_from_this.hpp>

using namespace std;
using namespace boost::asio;
using boost::system::error_code;
using tcp = boost::asio::ip::tcp;

class ConnectionHandler : public boost::enable_shared_from_this<ConnectionHandler> {
private:
    tcp::socket _Socket;
    string      _Message = "Message From Server!\n";
    char        _Data[1024];

public:
    typedef boost::shared_ptr<ConnectionHandler> pointer;

    ConnectionHandler(io_service& io_service)
        : _Socket{io_service}, _Data{0} {}

    static pointer Create(io_service& io_service) {
        return pointer(new ConnectionHandler(io_service));
    }

    tcp::socket& Socket() {
        return _Socket;
    }

    void Start() {
        _Socket.async_read_some(buffer(_Data, 1024),
            bind(&ConnectionHandler::handle_read,
                shared_from_this(),
                placeholders::error,
                placeholders::bytes_transferred));

        _Socket.async_write_some(buffer(_Message),
            bind(&ConnectionHandler::handle_write,
                shared_from_this(),
                placeholders::error,
                placeholders::bytes_transferred));
    }

    void handle_read(const error_code& error, size_t bytes_transferred) {
        if (!error) {
            // 添加字符串终止符,确保输出正确
            _Data[bytes_transferred] = '\0';
            cout << "Received: " << _Data << endl;

            // 重置缓冲区,清除旧数据残留
            memset(_Data, 0, sizeof(_Data));

            // 再次发起异步读操作,等待下一条消息
            _Socket.async_read_some(buffer(_Data, 1024),
                bind(&ConnectionHandler::handle_read,
                    shared_from_this(),
                    placeholders::error,
                    placeholders::bytes_transferred));
        } else {
            cerr << "Read error: " << error.message() << endl;
        }
    }

    // 新增handle_write实现,处理写操作结果
    void handle_write(const error_code& error, size_t bytes_transferred) {
        if (error) {
            cerr << "Write error: " << error.message() << endl;
        }
    }
};

class Server {
private:
    tcp::acceptor Acceptor;

    void StartAccept() {
        ConnectionHandler::pointer connection = ConnectionHandler::Create((io_context&)Acceptor.get_executor().context());

        Acceptor.async_accept(connection->Socket(),
            bind(&Server::handle_accept, this, connection, placeholders::error));
    }

public:
    Server(io_service& io_service)
        : Acceptor{io_service, tcp::endpoint(tcp::v4(), 1234)} {
        StartAccept();
    }

    void handle_accept(ConnectionHandler::pointer connection, const error_code& error) {
        if (!error) {
            connection->Start();
        }
        StartAccept();
    }
};

int main() {
    try {
        io_service io_service;
        Server server(io_service);
        io_service.run();
    } catch (exception& e) {
        cerr << e.what() << endl;
    }
    return 0;
}

额外说明

  • TCP是流协议,async_read_some仅保证读取至少1字节数据,若需完整读取每条消息,建议使用长度前缀或分隔符的方式定义消息边界,配合async_read实现完整消息读取。
  • 确保客户端发送消息后保持连接,若客户端发送完第一条消息就关闭连接,服务器会触发读错误,停止后续读操作。

内容的提问来源于stack exchange,提问作者Iman Abdollahzadeh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 21:00:33