c++ - Boost ASIO ip tcp iostream expires_from_now doesn't result in an error when connection fails
问题描述
We've come across a strange situation where our code reports that it has successfully opened a connection to an unreachable address. But it only happens when we actively reduce the time-out for a boost::asio::ip::tcp::iostream
:
void Connect(std::string address, std::string port) {
std::cout << "Waiting to connect: " << address << " at port " << port << "\n";
boost::asio::ip::tcp::iostream s;
s.expires_from_now(std::chrono::seconds(5));
s.connect(address, port);
if (!s) {
std::cout << "Unable to connect: " << s.error().message() << "\n";
} else {
std::cout << "Success!" << "\n";
}
}
With the above code, connect("192.168.25.25", "1234");
will quickly report "Success!", even though the address is unreachable. If we remove the expires_from_now
, then we instead get "Unable to connect: Connection timed out" after about 2 minutes - as we expect.
I would have expected that changing the timeout using expires_from_now
would result in a time-out error state. We're using boost 1.68.
Is there any other way to find out that the time-out is reached, or perhaps more appropriately, whether the connection has been established?
解决方案
The "Success" indication just means that nothing has gone wrong yet. It does not mean that the connect
has succeeded. You chose not to wait to find out whether the connect succeeded or failed and to instead time out the wait for that result.
You cannot make a TCP connect operation fail early. The rules for the conditions under which a TCP connect attempt fails are part of the TCP specification and just setting a timeout won't change how long it takes the connection attempt to fail.
Querying for the remote_endpoint will however indicate an error condition if the connection has not been established, for example:
boost::system::error_code ec;
s.socket().remote_endpoint(ec);
if (ec)
{
std::cout << "Unable to connect\n";
}
推荐阅读
- laravel - 如何在 Laravel 中将 npm 与 docker 一起使用?
- oracle - 为什么在将查询转换为函数时出现错误
- c# - HttpClient导致验证码,而浏览器中的同一页面没有
- python - 如何将数据框列转换为 UTC 日期时间格式?
- sql - 在表第 2 部分中搜索相反的值
- cryptography - 如何将导出的 Cosmos SDK 私钥转换为 Keplr 或 Metamask 可以导入的格式?
- c++ - 将类对象转换为结构对象 C/C++
- docker - Neo4J Docker-compose 在启动时加载 CSV 数据
- android - 使用底部导航内的回收站视图显示数据
- prolog - 如何通过其他关系延长理解连接