这与我的问题here有关。我正在寻找一种在boost::asio::read
上添加超时的方法。谢谢你的回答。我学习了如何使用boost::asio::async_read
模拟阻止读取超时。这很有效。
我正在尝试为阻止wite延迟扩展相同的内容。基本上尝试使用超时执行boost::asio::write
。如果我只是用boost::asio::async_read
替换boost::asio::async_write
,那么在读取时here工作的逻辑似乎不适用于写入。实际上这样做会使每次写入花费大约2-3秒的时间,这与我试图传输的数据非常长。
在进行超时时,write是否有不同的机制?是否有一个带有超时的boost::asio::write
的例子?
所以,基本上我需要知道如何基于boost::asio::write
进行超时?
根据示例here发布我正在尝试的以下代码:
#include <type_traits>
template<class Stream, class ConstBufferSequence, class Handler>
auto async_write_with_timeout(Stream& stream, ConstBufferSequence&& sequence, std::size_t millis, Handler&& handler)
{
using handler_type = std::decay_t<Handler>;
using buffer_sequence_type = std::decay_t<ConstBufferSequence>;
using stream_type = Stream;
struct state_machine : std::enable_shared_from_this<state_machine>
{
state_machine(stream_type& stream, buffer_sequence_type sequence, handler_type handler)
: stream_(stream)
, sequence_(std::move(sequence))
, handler_(std::move(handler))
{}
void start(std::size_t millis)
{
timer_.expires_from_now(boost::posix_time::milliseconds(millis));
timer_.async_wait(strand_.wrap([self = this->shared_from_this()](auto&& ec) {
self->handle_timeout(ec);
}));
boost::asio::async_write(stream_, sequence_,
strand_.wrap([self = this->shared_from_this()] (auto&& ec, auto size){
self->handle_write(ec, size);
}));
}
void handle_timeout(boost::system::error_code const& ec)
{
if (not ec and not completed_)
{
boost::system::error_code sink;
stream_.cancel(sink);
}
}
void handle_write(boost::system::error_code const& ec, std::size_t size)
{
assert(not completed_);
boost::system::error_code sink;
timer_.cancel(sink);
completed_ = true;
handler_(ec, size);
}
stream_type& stream_;
buffer_sequence_type sequence_;
handler_type handler_;
boost::asio::io_service::strand strand_ { stream_.get_io_service() };
boost::asio::deadline_timer timer_ { stream_.get_io_service() };
bool completed_ = false;
};
auto psm = std::make_shared<state_machine>(stream,
std::forward<ConstBufferSequence>(sequence),
std::forward<Handler>(handler));
psm->start(millis);
}
std::size_t WriteData(boost::asio::ip::tcp::socket& socket,
std::vector<unsigned char> & buffer,
unsigned int size_to_write,
boost::system::error_code& ec) {
buffer.resize(size_to_write);
ec.clear();
std::size_t bytes_written = 0;
auto& executor = socket.get_io_service();
async_write_with_timeout(socket, boost::asio::buffer(buffer),
2000, // 2 seconds for example
[&](auto&& err, auto size){
ec = err;
bytes_written = size;
});
// todo: use a more scalable executor than spawning threads
auto future = std::async(std::launch::async, [&] {
if (executor.stopped()) {
executor.reset();
}
executor.run();
});
future.wait();
return bytes_written;
}