يمكنك تعيين SO_RCVTIMEO وSO_SNDTIMEO خيارات مأخذ في دفعة اسيو؟

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

  •  08-07-2019
  •  | 
  •  

سؤال

ويمكنك تعيين SO_RCVTIMEO وSO_SNDTIMEO خيارات مأخذ في دفعة اسيو؟

وإذا كان الأمر كذلك كيف؟

ملاحظة وأنا أعلم أنك يمكن استخدام أجهزة ضبط الوقت بدلا من ذلك، ولكن أود أن أعرف عن هذه الخيارات مأخذ على وجه الخصوص.

هل كانت مفيدة؟

المحلول

وعلى الاطلاق! تعزيز اسيو يسمح لك للوصول إلى البيانات الأم / الكامنة، وهو في هذه الحالة هو المقبس نفسه. لذا، دعونا نقول لديك:

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

ودعونا نقول لكم لقد دعا بالفعل open أو bind أو بعض الدالة العضو الذي يجعل الواقع my_socket صالحة للاستعمال. ثم، للحصول على قيمة 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>);
}

وهكذا فإنه يوجد لديك! اسيو دفعة ويتيح لك أن تفعل أشياء كثيرة بسرعة أكبر مما كنت على خلاف ذلك قد تكون قادرة على، ولكن هناك الكثير من الأشياء التي لا تزال بحاجة المكالمات مكتبة مأخذ العادية ل. يحدث هذا ليكون واحدا منهم.

نصائح أخرى

ولا يبدو أن في صلب Boost.Asio (اعتبارا من دفعة الحالي 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;

و(من الواضح، وأنا لا أقترح عليك حقن الطبقة timeval في مساحة الاسم boost::asio::detail::socket_option، ولكن لا أستطيع أن أفكر في فكرة جيدة لاستخدامها في الوقت الراهن. :-P)

وتحرير: بلدي تطبيق نموذج من 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_;
};

وهناك عمل حول سهل لهذه المشكلة يتمثل في استخدام القراءة والكتابة الأم وظائف.

لكتابة مع مهلة 1sec و:

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

لقراءة مع مهلة 1sec و:

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

وهذا سار على ما يرام بالنسبة لي.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top