views:

1728

answers:

2

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

If so how?

Note I know you can use timers instead, but I'd like to know about these socket options in particular.

+2  A: 

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:

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)

Edit: My sample implementation of socket_option::timeval, based on 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_;
};
Chris Jester-Young
Couldn't I just do:typedef boost::asio::detail::socket_option::integer<SOL_SOCKET, SO_SNDTIMEO> send_timeout;And the same for the recv timeout? Why do you need the timeval struct as well?
Brian R. Bondy
Hahaha, you'll see in the first version of my answer, that's what I thought as well. However, read http://www.opengroup.org/onlinepubs/009695399/functions/setsockopt.html and you'll see that the timeout values use timeval, not int.
Chris Jester-Young
+1  A: 

Absolutely! Boost ASIO allows you to access the native/underlying data, which in this case is the SOCKET itself. 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. Then, to get the underlying SOCKET value, call:

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. This happens to be one of them.

Brian
all but the lowest-level send/recv functions have for (;;) loops around the calls that explicitly catch EAGAIN. This effectively makes SO_{SND,RCV}TIMEO options useless unless you discard 95% of the sending/receiving functions in Boost. Thus, it is moot that they allow you to set the options, because the only way to take advantage of it is to not use the rest of the library...
Tom
Excellent point. I just hit this now. Sucks.
Rhythmic Fistman