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

Boost Asio中Socket显示已关闭的原因及无法读取数据排查

问题分析与修复

1. Socket状态判断逻辑完全反转

代码中判断socket是否打开的三元表达式逻辑颠倒:

std::cout << "Socket " << ((*current_socket).is_open() == 0 ? "is open" : "not open") << std::endl;

is_open()返回bool类型,true(非0值)表示socket已打开,但这里的逻辑是当is_open() == 0(socket未打开)时输出"is open",完全搞反了判断条件,所以即使socket正常打开,也会错误输出"Socket not open"。

正确写法:

std::cout << "Socket " << (current_socket->is_open() ? "is open" : "not open") << std::endl;

2. 错误码校验对象错误

代码中初始化了一个未使用的空错误码ec,却用它来判断socket打开是否失败:

const boost::system::error_code ec; // 默认构造的错误码,值为0
// ...
(*current_socket).open(protocol, err_code);

if (ec.value() != 0) { // 错误地校验了ec,而非实际接收错误的err_code
    std::cout<<"Error in open socket"<<std::endl;
    return 1;
}

open操作的错误信息是通过err_code返回的,但后续校验的却是未初始化的ec,导致即使open失败也无法检测到错误。

正确校验方式:

current_socket->open(protocol, err_code);

if (err_code) { // 直接判断错误码对象,等价于err_code.value() !=0
    std::cout<<"Error in open socket: "<<err_code.message()<<std::endl;
    return 1;
}

3. 无效的端点遍历逻辑

调用asio::connect(*current_socket, iterator)之后,代码尝试遍历剩余端点:

asio::connect(*current_socket, iterator);

tcp::resolver::iterator end;
while (iterator != end)
{
    boost::asio::ip::tcp::endpoint endpoint = *iterator++;
    std::cout << "endpoint " << endpoint << std::endl;
}

asio::connect会自动遍历解析得到的端点迭代器,直到成功连接或遍历结束,此时iterator已经指向end(),所以后续循环不会输出任何内容。如果要打印所有解析得到的端点,需要在connect之前遍历,或者先保存迭代器副本。

4. 冗余的Socket对象

代码中创建了栈上的socket对象,但全程未使用,属于冗余代码,可直接删除:

tcp::socket socket(io_service_test); // 未使用,可删除

修复后的完整代码示例

#include <iostream>
#include <istream>
#include <ostream>
#include <string>
#include <system_error>

#include <boost/asio.hpp>
#include <boost/asio/ssl.hpp>
#include <boost/lexical_cast.hpp>

namespace asio = boost::asio;
namespace ssl = boost::asio::ssl;
using tcp = boost::asio::ip::tcp;

int main()
{
    const std::string target_URL { "google.com" };
    int target_port {80};

    boost::asio::io_service io_service_test;

    std::string port_str = boost::lexical_cast<std::string>(target_port);

    tcp protocol = tcp::v4();
    tcp::resolver::query resolver_query(protocol, target_URL, port_str, tcp::resolver::query::numeric_service);
    tcp::resolver resolver(io_service_test);

    try {
        tcp::resolver::iterator iterator = resolver.resolve(resolver_query);
        
        // 先打印所有解析得到的端点
        std::cout << "Resolved endpoints:" << std::endl;
        for (auto iter = iterator; iter != tcp::resolver::iterator(); ++iter) {
            std::cout << "endpoint " << *iter << std::endl;
        }

        std::shared_ptr<tcp::socket> current_socket = std::make_shared<tcp::socket>(io_service_test);

        boost::system::error_code err_code;
        current_socket->open(protocol, err_code);

        if (err_code) {
            std::cout<<"Error in open socket: "<<err_code.message()<<std::endl;
            return 1;
        }

        asio::connect(*current_socket, iterator);

        std::cout << "Socket " << (current_socket->is_open() ? "is open" : "not open") << std::endl;
        
        // 发送HTTP GET请求示例
        std::string request = "GET / HTTP/1.1\r\nHost: google.com\r\nConnection: close\r\n\r\n";
        asio::write(*current_socket, asio::buffer(request), err_code);
        if (err_code) {
            std::cout<<"Error sending request: "<<err_code.message()<<std::endl;
            return 1;
        }

        // 读取响应数据
        char buffer[1024];
        size_t bytes_read;
        while ((bytes_read = current_socket->read_some(asio::buffer(buffer), err_code)) > 0) {
            std::cout.write(buffer, bytes_read);
        }
        if (err_code != asio::error::eof) {
            std::cout<<"Error reading response: "<<err_code.message()<<std::endl;
            return 1;
        }

        current_socket->shutdown(tcp::socket::shutdown_both, err_code);
        current_socket->close();

    }
    catch(const boost::wrapexcept<boost::system::system_error> &ex){
        std::cout << "Error code = " << ex.code()  << " message: " << ex.what() << std::endl;
        return 1;
    }
    catch (const std::system_error &e) {
        std::cout << "Error code = " << e.code()  << " message: " << e.what() << std::endl;
        return e.code().value();
    }

    return 0;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 21:25:54