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
相关产品推荐
相关产品推荐

