【问题标题】:Set timeout for boost socket.connect为 boost socket.connect 设置超时
【发布时间】:2015-12-17 23:23:22
【问题描述】:

我在tcp::socket 上使用boost::asio::connect。当一切正常时,connect 立即返回,但在网络不佳时,connect 在等待 15 秒的日志后超时。我不能等那么久,所以想减少超时。不幸的是,到目前为止我还没有遇到任何解决方案。

我看到了 async_wait 与deadline_timer 一起使用的解决方案,但所有这些示例都用于接收/发送操作,而不是用于连接。

谁能帮我提供boost::asio::connect(socket, endpoints); 的示例代码。要求是它应该在 5 秒而不是 15 秒内超时。

【问题讨论】:

  • 我认为在使用 boost 库时我不能混合 posix api 调用?
  • 此外,该链接谈到在连接的套接字中设置超时,而我的问题是如何为连接调用本身设置超时。
  • 您只需在 5 秒内完成其他操作。您不需要以任何特殊方式使连接超时。只是不要等待连接。
  • @DavidSchwartz 当然可以要求取消异步操作。 (您不想在已经失效的对象上接收完成处理程序)

标签: c++ sockets boost boost-asio asyncsocket


【解决方案1】:

你看过下面的example吗?它包含一个带有超时的示例代码async_connect

超时连接方法可以使用以下代码实现:

void connect(const std::string& host, const std::string& service,
  boost::posix_time::time_duration timeout)  {
// Resolve the host name and service to a list of endpoints.
tcp::resolver::query query(host, service);
tcp::resolver::iterator iter = tcp::resolver(io_service_).resolve(query);

// Set a deadline for the asynchronous operation. As a host name may
// resolve to multiple endpoints, this function uses the composed operation
// async_connect. The deadline applies to the entire operation, rather than
// individual connection attempts.
deadline_.expires_from_now(timeout);

// Set up the variable that receives the result of the asynchronous
// operation. The error code is set to would_block to signal that the
// operation is incomplete. Asio guarantees that its asynchronous
// operations will never fail with would_block, so any other value in
// ec indicates completion.
boost::system::error_code ec = boost::asio::error::would_block;

// Start the asynchronous operation itself. The boost::lambda function
// object is used as a callback and will update the ec variable when the
// operation completes. The blocking_udp_client.cpp example shows how you
// can use boost::bind rather than boost::lambda.
boost::asio::async_connect(socket_, iter, var(ec) = _1);

// Block until the asynchronous operation has completed.
do io_service_.run_one(); while (ec == boost::asio::error::would_block);

// Determine whether a connection was successfully established. The
// deadline actor may have had a chance to run and close our socket, even
// though the connect operation notionally succeeded. Therefore we must
// check whether the socket is still open before deciding if we succeeded
// or failed.
if (ec || !socket_.is_open())
  throw boost::system::system_error(
      ec ? ec : boost::asio::error::operation_aborted);
}

【讨论】:

  • 当 timeout 的值很小 ( boost::posix_time::seconds(1)) 时,这对我不起作用。代码“io_service_.run_one();”一直运行到一个事件完成,这似乎仅在 connect() 自然超时(15 秒)后才会发生)。我在循环中调用 io_service.poll_one() 获得了更多成功,直到 1 秒过去或 ec 更新
  • @aCuria 你能分享一下代码吗?还需要“计时器”吗?
  • @aCuria 一旦我根据blocking_tcp_client.cpp添加'check_deadline'相关逻辑,它就可以正常工作。
  • 最新版本的链接是什么?这仍然是推荐的方式吗?
  • 您还需要使用一个处理程序来截止时间_.async_wait() 以关闭套接字,如链接到示例中所示。 run_one() 对我来说很好(win/linux),超时 5s。在 boost 1.66+ 中,io_service 变为 io_context,deadline_timer 变为 stable_timer。
猜你喜欢
  • 1970-01-01
  • 2010-10-02
  • 2013-01-24
  • 2010-10-10
  • 2010-09-27
  • 2017-07-31
  • 1970-01-01
  • 2010-12-21
  • 2019-03-27
相关资源
最近更新 更多