Sie können SO_RCVTIMEO und SO_SNDTIMEO Socket-Optionen im Boost Asio eingestellt?

StackOverflow https://stackoverflow.com/questions/292997

  •  08-07-2019
  •  | 
  •  

Frage

können Sie einstellen, SO_RCVTIMEO und SO_SNDTIMEO Socket-Optionen im Boost Asio?

Wenn ja, wie?

Hinweis: Ich weiß, Sie Timer stattdessen verwenden können, aber ich möchte über diese Socket-Optionen insbesondere kennen.

War es hilfreich?

Lösung

Auf jeden Fall! Steigern Sie ASIO können Sie die nativen / zugrundeliegenden Daten zugreifen können, die in diesem Fall ist die Buchse selbst. Also, lassen Sie uns sagen, Sie haben:

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

Und lassen Sie uns sagen, dass Sie bereits open oder bind oder einige Memberfunktion aufgerufen haben, die tatsächlich my_socket nutzbar macht. Dann den darunter liegenden STECK Wert zu erhalten, rufen Sie:

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 haben Sie es! Boost-ASIO können Sie schnell viele Dinge mehr tun, als Sie sonst in der Lage sein könnte, aber es gibt eine Menge Dinge, die Sie immer noch die normalen Socket-Bibliothek fordert müssen. Dies geschieht, einer von ihnen sein.

Andere Tipps

Es scheint nicht in Boost.Asio gebaut werden (als aktueller Boost-SVN), aber, wenn Sie bereit sind, Ihre eigenen Klassen zu schreiben, um die boost::asio::detail::socket_option diejenigen zu simulieren, können Sie immer die Beispiele in boost/asio/socket_base.hpp folgen und Gehen Sie folgendermaßen vor:

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;

(Natürlich, ich behaupte nicht, dass Sie die timeval Klasse in den boost::asio::detail::socket_option Namensraum injizieren, aber ich kann nicht glauben, von einem guten im Moment zu verwenden. :-P)

Edit: Meine Beispielimplementierung von socket_option::timeval, basierend auf 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_;
};

Eine einfache Behelfslösung für dieses Problem wäre das native Lese zu verwenden und Funktionen schreiben.

mit 1 S Timeout Schreiben:

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);
}

mit 1 S Timeout Lesen:

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;
}

Das funktionierte gut für mich.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top