为异步发送缓冲区保留内存(提升 asio 套接字)
Reserving memory for asynchronous send buffers (boost asio sockets)
我正在尝试将即发即弃的 UDP 发送函数的实现从同步更改为异步。
当前简化的同步函数如下所示:
ssize_t UDPTransport::send_to(const char * buffer, size_t bufferSize) {
return mPSocket->send_to(boost::asio::buffer(buffer, bufferSize), mOutputEndpoint);
}
我已经设置了一个thread_group
,io_service::run()
设置使用它。但是,问题是我不能保证在此调用完成后buffer
会存在。 我需要存储缓冲区的内容,然后知道它何时可用,以便以后可以重用或删除它。 以下内容很简单,但是如果我发出两个send_to
调用,那么我不能保证handle_send
将以相同的顺序调用,我可能会pop
仍然需要的东西!
ssize_t UDPTransport::send_to(const char * buffer, size_t bufferSize) {
boost::asio::mutable_buffer b1 = boost::asio::buffer(buffer,bufferSize);
mMutex.lock();
mQueue.push(b1);
mPSocket->async_send_to(mQueue.back(), mOutputEndpoint,
boost::bind(&UDPTransport::handle_send, this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
mMutex.unlock();
return bufferSize;
}
void UDPTransport::handle_send(const boost::system::error_code& error,
std::size_t bytes_transferred)
{
mMutex.lock();
mQueue.pop();
mMutex.unlock();
}
存储异步缓冲区,然后在不再需要时将其清理的好方法是什么?
在线阅读更简单的方式可能在下面,但我不知道我是否相信它。 为什么共享指针会决定在调用处理程序之前不取消分配自身?
ssize_t UDPTransport::send_to(const char * buffer, size_t bufferSize)
{
auto buf = std::make_shared<std::string>(buffer, bufferSize);
mPSocket->async_send_to(boost::asio::buffer(*buf), mOutputEndpoint,
boost::bind(&UDPTransport::handle_send, this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
return bufferSize;
}
我通常做的是将其包装在继承自 std::enable_shared_from_this<> 的类中
,如下所示:class Sender : public std::enable_shared_from_this<Sender> {
public:
using CompletionHandler =
std::function<void(const boost::system::error_code& ec,
size_t bytes_transferred,
std::shared_ptr<Sender> sender)>;
~Sender() = default;
template<typename... Args>
static std::shared_ptr<Sender> Create(Args&&... args) {
return std::shared_ptr<Sender>(new Sender(std::forward<Args>(args)...));
}
void AsyncSendTo(const char* buffer, size_t buffer_size,
CompletionHandler completion_handler) {
data_.append(buffer, buffer_size);
socket.async_send_to(
boost::asio::buffer(data_), endpoint_,
[self = shared_from_this(),
completion_handler = std::move(completion_handler)]
(const boost::system::error_code& ec,
size_t bytes_transferred) mutable {
completion_handler(ec, bytes_transferred, std::move(self));
});
}
private:
Sender() = default;
Sender(const Sender&) = delete;
Sender(Sender&&) = delete;
Sender& operator=(const Sender&) = delete;
Sender& operator=(Sender&&) = delete;
SocketType socket_;
EndpointType endpoint_;
std::string data_;
}
显然,你必须保证completion_handler
的寿命。但除此之外,完成处理程序将在完成时返回有效std::shared_ptr<Sender>
,您可以对 Sender 携带的数据执行任何需要的操作。
在您发布的示例中,除非您首先在bind
中捕获它,否则buf
会离开范围并在返回时send_to
销毁。
脚注 1:可能需要删除这些std::move()
,具体取决于您的编译器在 lambda 方面是否兼容 C++14。
脚注2:远离bind
,除非你绝对需要利用它的动态性质。
相关文章:
- 提升 ASIO 无法识别计时器对象
- 缓慢提升ASIO
- 提升 Asio TCP 服务器 处理多个客户端
- 提升 ASIO - io_service 不要等待连接到线程
- 提升 asio 并发计时器取消问题与链
- 提升::Asio 异步聊天客户端停止与服务器通信
- 提升 asio io_content运行非阻塞
- 提升 ASIO Async_receive崩溃程序
- 使用提升 asio 时出现"resolve: Host not found (authoritative)"异常
- 获取加速::p rocess::子的退出代码 在提升::asio::io_service?
- 提升 asio 串行端口"end of file"
- 提升 ASIO 打开多个插座
- 提升 ASIO TCP 套接字 1.70 不向后兼容
- 为异步发送缓冲区保留内存(提升 asio 套接字)
- 提升 ASIO async_tcp_echo_server的例子
- 调用socket.remote_endpoint(提升 asio 库)线程安全性
- 多次提升::ASIO 一次性async_send_to
- 可以提升 asio 帖子"overflow"队列
- 提升 ASIO transfer_exactly读取 0 字节
- 提升 Asio SSL 无法第二次接收数据(第一次确定)