C++ asio::读取超时
我需要知道如何在超时的情况下读取(同步或异步不重要)。我想检查设备是否与串行端口连接 为此,我使用C++ asio::读取超时,c++,boost,timeout,serial-port,boost-asio,C++,Boost,Timeout,Serial Port,Boost Asio,我需要知道如何在超时的情况下读取(同步或异步不重要)。我想检查设备是否与串行端口连接 为此,我使用asio::write,然后等待设备的响应 如果连接了设备asio::read(串行,boost::asio::buffer(&r,1))工作正常,但如果没有设备,程序将停止,这就是我需要超时的原因 我知道我需要一个截止时间计时器,但我不知道如何在异步读取功能中使用它 template <typename SyncReadStream, typename MutableBufferSequen
asio::write
,然后等待设备的响应
如果连接了设备asio::read(串行,boost::asio::buffer(&r,1))
工作正常,但如果没有设备,程序将停止,这就是我需要超时的原因
我知道我需要一个截止时间计时器
,但我不知道如何在异步读取
功能中使用它
template <typename SyncReadStream, typename MutableBufferSequence>
void readWithTimeout(SyncReadStream& s, const MutableBufferSequence& buffers, const boost::asio::deadline_timer::duration_type& expiry_time)
{
boost::optional<boost::system::error_code> timer_result;
boost::asio::deadline_timer timer(s.get_io_service());
timer.expires_from_now(expiry_time);
timer.async_wait([&timer_result] (const boost::system::error_code& error) { timer_result.reset(error); });
boost::optional<boost::system::error_code> read_result;
boost::asio::async_read(s, buffers, [&read_result] (const boost::system::error_code& error, size_t) { read_result.reset(error); });
s.get_io_service().reset();
while (s.get_io_service().run_one())
{
if (read_result)
timer.cancel();
else if (timer_result)
s.cancel();
}
if (*read_result)
throw boost::system::system_error(*read_result);
}
举个例子来说明它是如何工作的,这将非常有帮助
我知道有许多类似的线程,我读了很多,但我找不到一个解决方案,帮助我解决我的问题 从本质上来说,没有一个简单的答案,因为即使您进行异步读取,也永远不会调用回调,而且您现在的周围有一个松散的线程
您正确地认为,deadline\u timer
是可能的解决方案之一,但它需要一些处理和共享状态。这里有一个问题,但这是针对异步连接的,当它没事做时,它返回有一件很酷的事情<代码>读取
不会这样做,最坏的情况是——它会因为无效资源而崩溃并烧掉。因此,截止时间计时器
是您的选择之一,但实际上有一个更简单的选项,有点像这样:
boost::thread *newthread = new boost::thread(boost::bind(&::try_read));
if (!newthread->timed_join(boost::posix_time::seconds(5))) {
newthread->interrupt();
}
基本上,在另一个线程中进行读取,并在超时时将其杀死。你应该仔细阅读
如果中断,请确保所有资源都已关闭。在
async\u read
中不要使用截止时间计时器。但您可以启动两个异步进程:
串行端口上的异步读取进程。具有取消其上所有异步操作的方法
具有所需超时的截止时间计时器。在deadline\u timer的完成处理程序中
可以取消
串行端口。这将关闭async\u read
操作,并调用其完成处理程序,但出现错误
代码:
#包括
#包括
#包括
#包括
#包括
类定时连接
{
公众:
定时连接(int超时):
计时器(io_服务,boost::posix_时间::秒(超时)),
串行端口(io服务)
{
}
void start()
{
计时器\异步\等待
(
boost::bind
(
&定时连接::停止,这是
)
);
//连接插座
//写入套接字
//从串行端口异步读取
boost::asio::异步读取
(
串行端口,boost::asio::buffer(缓冲区),
boost::bind
(
&定时连接::句柄读取,此,
boost::asio::占位符::错误
)
);
io_服务_uu.run();
}
私人:
无效停止()
{
串行端口取消();
}
无效句柄读取(const boost::system::error\u code&ec)
{
国际单项体育联合会(欧共体)
{
//处理错误
}
其他的
{
//做点什么
}
}
私人:
boost::asio::io_服务io_服务;
boost::asio::截止时间\u计时器\uu;
boost::asio::串行端口串行端口;
boost::数组缓冲区;
};
int main()
{
定时_连接接头(5);
连接开始();
返回0;
}
有一次,库作者提出了以下方法(本例涉及tcp::socket
,但您可以使用串行端口):
void set_结果(可选*a,错误代码b)
{
a->重置(b);
}
模板
无效读取超时的\u(tcp::socket和sock,
常量可变缓冲区序列和缓冲区)
{
可选的定时器输出结果;
截止期计时器(sock.io_service());
timer.expires_from_now(秒(1));
异步等待(boost::bind(set_result,&timer_result,_1));
可选的读取结果;
异步读取(sock、缓冲区、,
boost::bind(set_result,&read_result,_1));
sock.io_service().reset();
while(sock.io_service().run_one())
{
如果(读取结果)
timer.cancel();
else if(计时器\u结果)
sock.cancel();
}
如果(*读取结果)
抛出系统错误(*读取结果);
}
没有为我编译。这是我对他的代码的改进版本,它工作得非常好。它使用lambdas来摆脱set\u result
helper函数
template <typename SyncReadStream, typename MutableBufferSequence>
void readWithTimeout(SyncReadStream& s, const MutableBufferSequence& buffers, const boost::asio::deadline_timer::duration_type& expiry_time)
{
boost::optional<boost::system::error_code> timer_result;
boost::asio::deadline_timer timer(s.get_io_service());
timer.expires_from_now(expiry_time);
timer.async_wait([&timer_result] (const boost::system::error_code& error) { timer_result.reset(error); });
boost::optional<boost::system::error_code> read_result;
boost::asio::async_read(s, buffers, [&read_result] (const boost::system::error_code& error, size_t) { read_result.reset(error); });
s.get_io_service().reset();
while (s.get_io_service().run_one())
{
if (read_result)
timer.cancel();
else if (timer_result)
s.cancel();
}
if (*read_result)
throw boost::system::system_error(*read_result);
}
模板
void readWithTimeout(SyncReadStream&s、const MutableBufferSequence&buffers、const boost::asio::deadline\u timer::duration\u type和Expiration\u time)
{
boost::可选的定时器结果;
boost::asio::deadline_timer(s.get_io_service());
timer.expires\u from\u now(expire\u time);
timer.async_wait([&timer_result](const boost::system::error_code&error){timer_result.reset(error);});
boost::可选的读取结果;
boost::asio::async_read(s,buffers,[&read_result](const boost::system::error_code&error,size_t){read_result.reset(error);});
s、 获取io_服务().reset();
而(s.get_io_service().run_one())
{
如果(读取结果)
timer.cancel();
else if(计时器\u结果)
s、 取消();
}
如果(*读取结果)
抛出boost::system::system\u错误(*读取结果);
}
问题明确说明他使用的是串行设备,而不是TCP端点。如果他使用*nix,UNIX套接字可能是一个选项,但是操作系统没有声明,它们破坏了可移植性。@TC1,当然,编辑了代码。从概念上讲,Asio抽象它的方式没有任何变化。你确定Asio i/o操作是一个中断点吗?有人能够证实这一点吗?这能解决问题吗
template <typename SyncReadStream, typename MutableBufferSequence>
void readWithTimeout(SyncReadStream& s, const MutableBufferSequence& buffers, const boost::asio::deadline_timer::duration_type& expiry_time)
{
boost::optional<boost::system::error_code> timer_result;
boost::asio::deadline_timer timer(s.get_io_service());
timer.expires_from_now(expiry_time);
timer.async_wait([&timer_result] (const boost::system::error_code& error) { timer_result.reset(error); });
boost::optional<boost::system::error_code> read_result;
boost::asio::async_read(s, buffers, [&read_result] (const boost::system::error_code& error, size_t) { read_result.reset(error); });
s.get_io_service().reset();
while (s.get_io_service().run_one())
{
if (read_result)
timer.cancel();
else if (timer_result)
s.cancel();
}
if (*read_result)
throw boost::system::system_error(*read_result);
}