首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >udp套接字上的boost asio多重async_send

udp套接字上的boost asio多重async_send
EN

Stack Overflow用户
提问于 2013-10-28 11:26:15
回答 2查看 3.8K关注 0票数 4

在boost::asio中有火和忘记udp套接字的方法安全吗?

所以如果我有这样的代码

代码语言:javascript
运行
复制
 socket.async_send(buffer(somedata1),write_handler);
 socket.async_send(buffer(somedata2),write_handler);
 socket.async_send(buffer(somedata3),write_handler);
 socket.async_send(buffer(somedata4),write_handler);

我是否保证这不会失败--这意味着在接收端点,我将得到4个包含somedata1、somedata2、somedata3、somedata4的数据包?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-10-28 17:59:45

没有保证仅仅是因为底层协议没有保证。

只要在socket.async_send()期间提供给缓冲区的底层内存在调用处理程序之前仍然有效,并且没有其他线程对socket进行并发调用,那么socket.async_send()的条件就满足了,并且应该是安全的。

对于实现细节,basic_datagram_socket::async_send()将让它的服务创建一个非组合操作(reactive_socket_send_opwin_iocp_socket_send_op)。然后,该服务将让它的reactor启动操作。一些反应堆实现可能试图立即运行操作;否则,操作将根据操作类型(读或写)添加到特定于套接字文件描述符的队列中。操作队列允许对给定的文件描述符执行多个读或写操作。

票数 2
EN

Stack Overflow用户

发布于 2013-10-28 17:09:07

不,这肯定是不安全的,asio async_*函数的async_*none被记录为“失火和遗忘”。

用于发送缓冲区的boost asio引用声明:“虽然缓冲区对象可能在必要时被复制,但底层内存块的所有权由调用方保留,这必须保证它们在调用处理程序之前仍然有效。”

如果您需要“触发和忘记”方法,那么您将需要一个类来管理连接并为您缓冲数据包。下面是一个使用deque缓冲数据包的示例:

代码语言:javascript
运行
复制
class Connection : public boost::enable_shared_from_this<Connection>
{
  boost::asio::ip::udp::socket socket_;
  std::deque<std::vector<char> > tx_queue_;

  /// transmit the packet at the head of the queue
  void transmit()
  {
    socket_.async_send(
      boost::asio::buffer(&tx_queue_.front()[0], tx_queue_.front().size()),
      boost::bind(&Connection::write_callback,
                  boost::weak_ptr<Connection>(shared_from_this()),
                  boost::asio::placeholders::error,
                  boost::asio::placeholders::bytes_transferred));
  }

  /// The function called whenever a write event is received.
  void write_handler(boost::system::error_code const& error,
                     size_t /* bytes_transferred */)
  {
    tx_queue_.pop_front();
    if (error)
      ; // handle the error, it may be a disconnect.
    else
      if (!tx_queue_.empty())
        transmit();
  }

  /// Static callback function.
  /// It ensures that the object still exists and the event is valid
  /// before calling the write handler.
  static void write_callback(boost::weak_ptr<Connection> ptr,
                             boost::system::error_code const& error,
                             size_t bytes_transferred)
  {
    boost::shared_ptr<Connection> pointer(ptr.lock());
    if (pointer && (boost::asio::error::operation_aborted != error))
      pointer->write_handler(error, bytes_transferred);
  }

  /// Private constructor to enusure the class is created as a shared_ptr.
  explicit Connection(boost::asio::io_service& io_service) :
    socket_(io_service),
    tx_queue_()
  {}

public:

  /// Factory method to create an instance of this class.
  static boost::shared_ptr<Connection> create(boost::asio::io_service& io_service)
  { return boost::shared_ptr<Connection>(new Connection(io_service)); }

  /// Destructor, closes the socket to cancel the write callback 
  /// (by calling it with error = boost::asio::error::operation_aborted)
  /// and free the weak_ptr held by the call to bind in the transmit function.
  ~Connection()
  { socket_.close(); }

  /// add the packet to the end of the queue and send it ASAP.
#if defined(BOOST_ASIO_HAS_MOVE)
  void send(std::vector<char>&& packet)
#else
  void send(const std::vector<char>& packet)
#endif
  {
    bool queue_empty(tx_queue_.empty());
    tx_queue_.push_back(packet);
    if (queue_empty)
      transmit();
  }
};
票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/19633544

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档