提升io_service不会重置

boost io_service doesn't reset

本文关键字:service io 提升      更新时间:2023-10-16

>我正在尝试为升压套接字实现一个ConnectWithTimeout函数。所以我使用我在这里找到的例子之一。这在第一次尝试中非常有效,但 io_service.run_one(( 会立即返回超时或取消错误。

这是我的代码

using NetStatus = boost::system::error_code;
NetStatus handleWait(const NetStatus& error)
{
return boost::asio::error::timed_out;
}
NetStatus handleConnect(const NetStatus& error)
{
// The async_connect() function automatically opens the socket at the start
// of the asynchronous operation. If the socket is closed at this time then
// the timeout handler must have run first.
if (!m_socket.is_open())
return boost::asio::error::timed_out;
// Otherwise, a connection has been established.  Update the timer state
// so that the timeout handler does not close the socket.
m_connectionTimeoutTimer.cancel();
return error;
}
void connectWithTimeout(boost::asio::ip::tcp::endpoint& endpoint, NetStatus& e)
{
// Stop last time's waiting objects
m_socket.cancel()
m_connectionTimeoutTimer.cancel();
m_ioService.stop();
m_ioService.reset();
// Set-up new objects to wait
m_connectionTimeoutTimer.expires_from_now(boost::posix_time::seconds(5));
m_connectionTimeoutTimer.async_wait([this, &e](const NetStatus& error) { e = handleWait(error); } );
m_socket.async_connect(endpoint,    [this, &e](const NetStatus& error) { e = handleConnect(error); } );
// Block until one of them is done
m_ioService.run_one(e);
}
boost::asio::ip::tcp::socket m_socket;
boost::asio::deadline_timer m_connectionTimeoutTimer;

在循环中运行时,我看到的结果是: 超时(按预期在 5 秒后( 取消(立即( 超时(立即( 取消(立即( 超时(立即( 取消(立即( 超时(立即( ...

任何人都可以帮助发现我做错了什么吗?

您是否正在关闭每个循环之间的套接字?您在同一个m_socket实例上调用async_connect,但我没有看到套接字关闭的位置。您可能在尝试连接已打开的套接字时遇到错误。尝试m_socket.close()而不是m_socket.cancel()

好的,所以我找到了答案,似乎将处理程序从io_service中取出的唯一方法是使用 run 或 run_one、reset 等调用它。 是我得到的最终代码,如果有人感兴趣:

#include <iostream>
#include <string>
#include <boost/asio.hpp>
#include <boost/filesystem.hpp>
#include <boost/iostreams/filtering_streambuf.hpp>
#include <boost/iostreams/copy.hpp>
#include <boost/iostreams/filter/gzip.hpp>
#include <boost/timer/timer.hpp>
std::string bindToIp;
std::string ip;
int         port;
auto tcpConnectionTrials = 5ul;
using NetStatus = boost::system::error_code;
boost::asio::io_service m_ioService;
boost::asio::ip::tcp::socket   m_socket(m_ioService);
boost::asio::deadline_timer    connectionTimeoutTimer(m_ioService);
bool isTimedOut = false;
void handleWait(boost::asio::ip::tcp::socket& socket, const NetStatus& error)
{
if (error != boost::asio::error::operation_aborted)
{
isTimedOut = true;
socket.cancel();
socket.close();
}
}
void handleConnect(boost::asio::ip::tcp::socket& socket, const NetStatus& error)
{
if (error != boost::asio::error::operation_aborted)
{
// The async_connect() function automatically opens the socket at the start
// of the asynchronous operation. If the socket is closed at this time then
// the timeout handler must have run first.
if (socket.is_open())
{
connectionTimeoutTimer.cancel();
}
}
}

void connectWithTimeout(boost::asio::ip::tcp::socket& socket,
boost::asio::deadline_timer& connectionTimeoutTimer,
boost::asio::io_service& m_ioService,
boost::asio::ip::tcp::endpoint& endpoint,
NetStatus& e)
{
isTimedOut = false;
// Set-up new objects to wait
connectionTimeoutTimer.expires_from_now(boost::posix_time::seconds(5));
connectionTimeoutTimer.async_wait([&socket](const NetStatus& error)     { handleWait(socket, error); } );
socket.async_connect(endpoint,    [&socket, &e](const NetStatus& error) { e = error; handleConnect(socket, error); } );
// Block until one of them is done
m_ioService.run();
if (isTimedOut)
{
e = boost::asio::error::timed_out;
}
m_ioService.reset();
}
NetStatus connect()
{
NetStatus e;
boost::asio::ip::tcp::endpoint remoteEndpoint(boost::asio::ip::address_v4::from_string(ip.c_str()), port);
boost::asio::ip::tcp::endpoint localEndpoint(boost::asio::ip::address_v4::from_string(bindToIp.c_str()), 0);
std::cout <<  "Open socket: " << std::endl;
if (m_socket.open(boost::asio::ip::tcp::v4(), e))
{
std::cout << "Socket " << ": could not open!!!" << std::endl;
return e;
}
m_socket.set_option(boost::asio::socket_base::reuse_address(true));
m_socket.set_option(boost::asio::ip::tcp::no_delay(true));
std::cout << " binds to " << bindToIp << std::endl;
m_socket.bind(localEndpoint);
std::cout << " connect to " << ip  << std::endl;
connectWithTimeout(m_socket, connectionTimeoutTimer, m_ioService, remoteEndpoint, e);
return e;
}
int main(int argc, char *argv[])
{
bindToIp = argv[1];
ip = argv[2];
port = atoi(argv[3]);
for(int i =0; i < 10; i++)
{
auto e = connect();
if (!e)
{
std::cout << "GOOD!" << std::endl;
break;
}
else
{
std::cout << "Failed: " << e.message() << std::endl;
}
m_socket.close();
}
std::cout << "DONE!" << std::endl;
return 0;
}