简体   繁体   English

您可以在boost asio中设置SO_RCVTIMEO和SO_SNDTIMEO套接字选项吗?

[英]can you set SO_RCVTIMEO and SO_SNDTIMEO socket options in boost asio?

can you set SO_RCVTIMEO and SO_SNDTIMEO socket options in boost asio? 您可以在boost asio中设置SO_RCVTIMEO和SO_SNDTIMEO套接字选项吗?

If so how? 如果可以,怎么办?

Note I know you can use timers instead, but I'd like to know about these socket options in particular. 请注意,我知道您可以改用计时器,但是我想特别了解这些套接字选项。

It doesn't appear to be built into Boost.Asio (as of current Boost SVN), but, if you're willing to write your own classes to simulate the boost::asio::detail::socket_option ones, you can always follow the examples in boost/asio/socket_base.hpp and do the following: 它似乎没有内置到Boost.Asio中(从当前的Boost SVN开始),但是,如果您愿意编写自己的类来模拟boost::asio::detail::socket_option类,则可以随时遵循boost/asio/socket_base.hpp并执行以下操作:

typedef boost::asio::detail::socket_option::timeval<SOL_SOCKET, SO_SNDTIMEO>
    send_timeout;
typedef boost::asio::detail::socket_option::timeval<SOL_SOCKET, SO_RCVTIMEO>
    receive_timeout;

(Obviously, I'm not suggesting you inject the timeval class into the boost::asio::detail::socket_option namespace, but I can't think of a good one to use at the moment. :-P) (显然,我不建议您将timeval类注入boost::asio::detail::socket_option命名空间,但目前我想不出要使用的好方法。:-P)

Edit: My sample implementation of socket_option::timeval , based on socket_option::integer : 编辑:我的示例实现socket_option::timeval基于socket_option::integer

// Helper template for implementing timeval options.
template <int Level, int Name>
class timeval
{
public:
  // Default constructor.
  timeval()
    : value_(zero_timeval())
  {
  }

  // Construct with a specific option value.
  explicit timeval(::timeval v)
    : value_(v)
  {
  }

  // Set the value of the timeval option.
  timeval& operator=(::timeval v)
  {
    value_ = v;
    return *this;
  }

  // Get the current value of the timeval option.
  ::timeval value() const
  {
    return value_;
  }

  // Get the level of the socket option.
  template <typename Protocol>
  int level(const Protocol&) const
  {
    return Level;
  }

  // Get the name of the socket option.
  template <typename Protocol>
  int name(const Protocol&) const
  {
    return Name;
  }

  // Get the address of the timeval data.
  template <typename Protocol>
  ::timeval* data(const Protocol&)
  {
    return &value_;
  }

  // Get the address of the timeval data.
  template <typename Protocol>
  const ::timeval* data(const Protocol&) const
  {
    return &value_;
  }

  // Get the size of the timeval data.
  template <typename Protocol>
  std::size_t size(const Protocol&) const
  {
    return sizeof(value_);
  }

  // Set the size of the timeval data.
  template <typename Protocol>
  void resize(const Protocol&, std::size_t s)
  {
    if (s != sizeof(value_))
      throw std::length_error("timeval socket option resize");
  }

private:
  static ::timeval zero_timeval()
  {
    ::timeval result = {};
    return result;
  }

  ::timeval value_;
};

Absolutely! 绝对! Boost ASIO allows you to access the native/underlying data, which in this case is the SOCKET itself. Boost ASIO允许您访问本地/基础数据,在这种情况下为SOCKET本身。 So, let's say you have: 因此,假设您有:

boost::asio::ip::tcp::socket my_socket;

And let's say you've already called open or bind or some member function that actually makes my_socket usable. 假设您已经调用了openbind或某些使my_socket可用的成员函数。 Then, to get the underlying SOCKET value, call: 然后,要获取底层SOCKET值,请调用:

SOCKET native_sock = my_socket.native();
int result = SOCKET_ERROR;

if (INVALID_SOCKET != native_sock)
{
    result = setsockopt(native_sock, SOL_SOCKET, <the pertinent params you want to use>);
}

So there you have it! 所以你有它! Boost's ASIO lets you do many things more quickly than you otherwise might be able to, but there are a lot of things you still need the normal socket library calls for. Boost的ASIO使您可以比其他方式更快地执行许多操作,但是仍有许多事情仍需要常规套接字库调用。 This happens to be one of them. 这恰好是其中之一。

An easy work-around to this problem would be to use the native read and write functions. 解决此问题的一个简单方法是使用本机读取和写入功能。

For writing with 1sec timeout: 对于1秒超时的写入:

struct timeval tv = { 1, 0 };
setsockopt(socket.native_handle(), SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));
ssize_t nsent = ::write(socket->native_handle(), buff, size);
if (nsent > 0) {
  BOOST_LOG_TRIVIAL(debug) << "Sent " << nsent << " bytes to remote client " << ep;
} else if (nsent == 0) {
 BOOST_LOG_TRIVIAL(info) <<  "Client " << ep << " closed connection";
} else if (errno != EAGAIN) {
  BOOST_LOG_TRIVIAL(info) <<  "Client " << ep << " error: " <<     strerror(errno);
}

For reading with 1sec timeout: 对于1秒超时的阅读:

struct timeval tv = { 1, 0 };
setsockopt(socket.native_handle(), SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
ssize_t nread = ::read(socket.native_handle(), buff, audio_buff_size);
if (nread > 0) {
} else if (nread == 0) {
  BOOST_LOG_TRIVIAL(info) <<  "Source " << source << " server " << host << " closed connection";
  break;
} else if (errno != EAGAIN) {
  BOOST_LOG_TRIVIAL(info) <<  "Source " << source << " server " << host << " error: " << strerror(errno);
  break;
}

This worked fine for me. 这对我来说很好。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM