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.
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.
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_;
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With