提升 UDP 套接字上的 ASIO 多重async_send
boost asio multiple async_send on udp socket
在
boost::asio中开火并忘记使用udp套接字是否安全?
所以例如,如果我有这样的代码
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 ?
不,它肯定不安全,没有一个 asio async_* 函数被记录为"即发即弃"。
basic_datagram_socket::async_send缓冲区的 boost asio 参考指出:"尽管可以根据需要复制缓冲区对象,但底层内存块的所有权由调用方保留,调用方必须保证它们在调用处理程序之前保持有效。
如果您需要"即发即弃"的方法,则需要一个类来管理您的连接并为您缓冲数据包。下面是使用双端键缓冲数据包的示例:
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();
}
};
没有保证,仅仅是因为底层协议没有保证。
只要在socket.async_send()
期间提供给缓冲区的基础内存在调用处理程序之前仍然有效,并且没有其他线程对socket
进行并发调用,则满足socket.async_send()
条件,并且应该是安全的。
对于实现细节,basic_datagram_socket::async_send()
将使其服务创建单个非组合操作(reactive_socket_send_op
或win_iocp_socket_send_op
)。 然后,该服务将具有其reactor
启动操作。 一些反应堆实现可能会尝试立即运行操作;否则,操作将根据操作类型(读取或写入)添加到特定于套接字文件描述符的队列中。 操作队列允许多个读取或写入操作对于给定的文件描述符未完成。
相关文章:
- std::cout.imbue()多重调用
- 为什么std::async使用同一个线程运行函数
- 为什么可以将左值传递给"std::async",即使它引用了右值
- 我应该避免多重实现继承吗
- 使用用户定义的参数调用future/async并调用类方法
- 关于C++中具有多重继承"this"指针的说明
- 枚举类'classname'的多重定义
- 如果我将嵌套映射作为多重映射的值,如何将值插入内部映射?
- 链接阶段出现多重定义错误
- File.cpp.o:OpenPose 标志 CMakeFiles/.. 的多重定义/main.cpp.o:首先在这里定
- C++中模板化异常类的多重继承
- 使用 std::async 时死锁,将来作为成员
- 为什么我不能将引用作为 std::async 的函数参数传递
- std::async from std::async in windows xp
- Google Cloud Pubsub Async Streaming API in C++
- 在一个类中插入另一个类的多重集
- 脚本的多重定义::LState
- -fno-unwind-tables 和 -fno-async-unwind-tables 不起作用 NDK clang
- 如何制作带有对象的多重地图? - C++
- 更改多重映射容器中所有元素的键值