Stopping async_connect
Stopping async_connect
我目前使用Windows 7 64位,MSVC2010和Boost.Asio 1.57。我想连接到超时的 TCP 服务器。如果超时到期,我应该尽快关闭连接,因为 IP 地址(由用户选择)可能是错误的。
我知道我应该使用异步请求,因为同步请求不包含超时选项。所以我使用带有外部超时的async_connect。这是我在很多地方找到的解决方案,包括stackoverflow。
问题是下面的代码没有像我希望的那样运行。 async_connect 没有被 socket.close() "取消"。使用我的电脑,关闭套接字大约需要 15 秒才能完成,这使我的程序在一段时间内没有响应......我希望有一个体面的超时(大约 3 秒)并在这段时间之后关闭套接字,以便用户可以尝试使用另一个 IP 地址(从 HMI)连接
#include <iostream>
#include <boostasio.hpp>
#include <boostshared_ptr.hpp>
#include <boostbind.hpp>
using boost::asio::ip::tcp;
class tcp_client
{
public:
tcp_client(boost::asio::io_service& io_service, tcp::endpoint& endpoint, long long timeout = 3000000)
:m_io_service (io_service),
m_endpoint(endpoint),
m_timer(io_service),
m_timeout(timeout)
{
connect();
}
void stop()
{
m_socket->close();
}
private:
void connect()
{
m_socket.reset(new tcp::socket(m_io_service));
std::cout << "TCP Connection in progress" << std::endl;
m_socket->async_connect(m_endpoint,
boost::bind(&tcp_client::handle_connect, this,
m_socket,
boost::asio::placeholders::error)
);
m_timer.expires_from_now(boost::posix_time::microseconds(m_timeout));
m_timer.async_wait(boost::bind(&tcp_client::HandleWait, this, boost::asio::placeholders::error));
}
void handle_connect(boost::shared_ptr<tcp::socket> socket, const boost::system::error_code& error)
{
if (!error)
{
std::cout << "TCP Connection : connected !" << std::endl;
m_timer.expires_at(boost::posix_time::pos_infin); // Stop the timer !
// Read normally
}
else
{
std::cout << "TCP Connection failed" << std::endl;
}
}
public:
void HandleWait(const boost::system::error_code& error)
{
if (!error)
{
std::cout << "Connection not established..." << std::endl;
std::cout << "Trying to close socket..." << std::endl;
stop();
return;
}
}
boost::asio::io_service& m_io_service;
boost::shared_ptr<tcp::socket> m_socket;
tcp::endpoint m_endpoint;
boost::asio::deadline_timer m_timer;
long long m_timeout;
};
int main()
{
boost::asio::io_service io_service;
tcp::endpoint endpoint(boost::asio::ip::address_v4::from_string("192.168.10.74"), 7171); // invalid address
tcp_client tcpc(io_service, endpoint);
io_service.run();
system("pause");
}
我找到的唯一解决方案是在许多线程中运行 io_service:run(),并为每个连接创建一个新套接字。但是这个解决方案对我来说似乎无效,因为我必须指定多个线程,并且我不知道用户将在我的HMI中输入多少个错误的地址。是的,有些用户不如其他用户聪明...
我的代码有什么问题?如何以干净快速的方式中断TCP连接?
此致敬意普基尔
代码没有任何基本错误,它在我的 Linux 盒子上完全符合您的要求:
TCP Connection in progress
Connection not established...
Trying to close socket...
TCP Connection failed
real 0m3.003s
user 0m0.002s
sys 0m0.000s
笔记:
您可能会成功向
stop()
函数添加cancel()
调用:void stop() { m_socket->cancel(); m_socket->close(); }
不过,您应该检查超时的堕胎:
void HandleWait(const boost::system::error_code& error) { if (error && error != boost::asio::error::operation_aborted) { std::cout << "Connection not established..." << std::endl; std::cout << "Trying to close socket..." << std::endl; stop(); return; } }
否则,连接成功后计时器的隐式取消仍将关闭套接字:)
如果要并行运行(多次)连接尝试,则不需要更多线程甚至多个
io_service
。这就是 Boost Asio 的本质:您可以在单个线程上执行异步 IO 操作。这个答案给出了一个非常孤立的画面(即使连接是在那里使用 ZMQ 完成的):在 N 秒内两次提升 asio deadline_timer async_wait(N 秒)导致操作取消
另一个例子,这次是关于在单个
io_service
上独立超时多个会话:boost::asio::d eadline_timer::async_wait不触发回调
- 为什么std::async使用同一个线程运行函数
- 为什么可以将左值传递给"std::async",即使它引用了右值
- 使用用户定义的参数调用future/async并调用类方法
- WinSock2:connect() 提供"连接被拒绝"
- 使用 std::async 时死锁,将来作为成员
- 如何使用connect将qml按钮与同一类的cpp函数连接起来
- 为什么我不能将引用作为 std::async 的函数参数传递
- 在 QTextEdit 中使用指针或在 Qt-Creator 上使用 connect()
- std::async from std::async in windows xp
- Google Cloud Pubsub Async Streaming API in C++
- -fno-unwind-tables 和 -fno-async-unwind-tables 不起作用 NDK clang
- gnuradio c++ connect self() throw bad_weak_ptr
- std::async 如何工作:为什么它会调用这么多次复制/移动?
- 如何将函数指针传递给方法,以便它可以在Qt的connect()中使用?
- std::async 不会立即调用
- 在CTOR vs Connect方法中提升套接字与stream_socket端点
- async中没有匹配的函数(模板中未解析的类型)
- Make zmqpp::socket::connect a std::future
- C-Free and MySQL connect
- 当我使用Connect信号和插槽时,会出现此分解错误