我想从cin进行异步读取因此我有一段代码
client.h
...
boost::asio::posix::stream_descriptor input;
boost::asio::streambuf input_buffer
client.cpp
Client::Client(int argc, char **argv, boost::asio::io_service &io_service)
: tcp_socket(io_service)
, udp_socket(io_service)
, input(io_service, ::dup(STDIN_FILENO))
{
...
read_std_input();
}
void Client::read_std_input() {
async_read_until(input, input_buffer, '\n',
boost::bind(&Client::handle_std_read, this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
}
问题是:当我以正常方式[./client]运行我的客户端然后通过命令输入一些东西时,它就像魅力一样。 但是,当我通过[./client<测试]它抛出:
在抛出一个实例后终止调用 “增强:: exception_detail :: clone_impl
'what():assign:不允许操作中止
你知道问题可能是什么吗? 谢谢!
答案 0 :(得分:9)
Boost.Asio的POSIX面向流的描述符显然不支持常规文件。因此,如果test
是常规文件,则./client < test
在尝试将STDIN_FILENO
分配给stream_descriptor
时会导致posix::stream_descriptor::assign()
失败。 documentation州:
Boost.Asio包括添加的类,允许在POSIX文件描述符上执行同步和异步读写操作,例如管道,标准输入和输出以及各种设备(但不是常规文件)。
考虑通过管道将test
文件的内容传递给client
。
$ cat test | ./client
这是一个完整的示例程序和演示:
#include <iostream>
#include <boost/asio.hpp>
void handle_read(
const boost::system::error_code& error,
std::size_t bytes_transferred
)
{
std::cout << "read " << bytes_transferred << " bytes with "
<< error.message() << std::endl;
}
int main()
{
boost::asio::io_service io_service;
boost::asio::posix::stream_descriptor input(io_service);
// Assign STDIN_FILENO to the stream_descriptor. It will support
// pipes, standard input and output, and various devices, but NOT
// regular files.
boost::system::error_code error;
input.assign(STDIN_FILENO, error);
if (error)
{
std::cerr << error.message() << std::endl;
return -1;
}
boost::asio::streambuf input_buffer;
async_read_until(input, input_buffer, '\n', &handle_read);
io_service.run();
}
示范
$ ./client testing standard inputenter read 23 bytes with Success $ echo "this is a test" > test $ ./client < test Operation not permitted $ cat test | ./client read 15 bytes with Success
答案 1 :(得分:1)
Linux上的异步文件I / O仍然相当原始。尽管ASIO对异步文件I / O的支持在Windows中运行良好,但我在Linux上使用它并没有太多(运气)。
This is a previous SO question that provides some background on the issue
答案 2 :(得分:1)
Boost asio在Linux上使用epoll
系by default does not support files。
但有一种解决方法:如果您定义BOOST_ASIO_DISABLE_EPOLL
,那么asio将恢复为select
系统,文件将起作用。
答案 3 :(得分:0)
你可以试试这个最小的复制品吗?它适用于我的Ubuntu 64位盒子:
#include <boost/asio.hpp>
#include <boost/asio/posix/stream_descriptor.hpp>
#include <iostream>
int main()
{
using namespace boost::asio;
io_service io;
posix::stream_descriptor input(io);
input.assign(STDIN_FILENO);
streambuf input_buffer;
std::function<void()> loop = [&] {
async_read_until(input, input_buffer, '\n', [&](boost::system::error_code ec, size_t) {
if (ec)
std::cerr << ec.message();
else {
std::cout << "LOOP: '" << &input_buffer << "'\n";
loop();
}
});
};
loop();
io.run();
}
更新我想我可以重现问题 on Coliru :您能查看ulimit -a
的输出吗?