微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何在Windows中使用boost asioasynchronous读取命令行input?

我发现这个问题 ,询问如何asynchronous读取input,但只能使用POSIXstream描述符,这将不会在Windows上工作。 所以,我发现这个教程显示,而不是使用POSIXstream描述符,我可以使用boost::asio::windows::stream_handle 。

在这两个例子之后,我提出了下面的代码。 当我运行它时,我不能在命令提示符下键入任何内容,因为程序立即终止。 我希望它捕获来自用户的任何input,可能是一个std::string ,同时允许我的程序中的其他逻辑执行(即从Windows控制台执行asynchronousI / O)。

从本质上讲,我试图避免阻止我的程序,当它试图从stdin读取。 我不知道这是否可能在Windows中,因为我也发现这个post ,详细说明另一个用户在尝试做同样的事情时遇到的问题。

#define _WIN32_WINNT 0x0501 #define INPUT_BUFFER_LENGTH 512 #include <cstdio> #include <iostream> #define BOOST_THREAD_USE_LIB // For MinGW 4.5 - (https://svn.boost.org/trac/boost/ticket/4878) #include <boost/bind.hpp> #include <boost/asio.hpp> class Example { public: Example( boost::asio::io_service& io_service) : input_buffer( INPUT_BUFFER_LENGTH),input_handle( io_service) { // Read a line of input. boost::asio::async_read_until( input_handle,input_buffer,"rn",boost::bind( &Example::handle_read,this,boost::asio::placeholders::error,boost::asio::placeholders::bytes_transferred)); } void handle_read( const boost::system::error_code& error,std::size_t length); void handle_write( const boost::system::error_code& error); private: boost::asio::streambuf input_buffer; boost::asio::windows::stream_handle input_handle; }; void Example::handle_read( const boost::system::error_code& error,std::size_t length) { if (!error) { // Remove newline from input. input_buffer.consume(1); input_buffer.commit( length - 1); std::istream is(&input_buffer); std::string s; is >> s; std::cout << s << std::endl; boost::asio::async_read_until(input_handle,boost::asio::placeholders::bytes_transferred)); } else if( error == boost::asio::error::not_found) { std::cout << "Did not receive ending character!" << std::endl; } } void Example::handle_write( const boost::system::error_code& error) { if (!error) { // Read a line of input. boost::asio::async_read_until(input_handle,boost::asio::placeholders::bytes_transferred)); } } int main( int argc,char ** argv) { try { boost::asio::io_service io_service; Example obj( io_service); io_service.run(); } catch( std::exception & e) { std::cout << e.what() << std::endl; } std::cout << "Program has ended" << std::endl; getchar(); return 0; }

如何使用boost在C ++中独立于系统时间实现定时器callback

升压asio计时器不阻止读取呼叫

在Linux中加强安装

ipv4和ipv6从任何有效的地址

为什么boost asio函数expires_from_Now()取消deadline_timer?

使用gcc4.7在linux x64平台上升级协程和asiotesting版本失败

如何使用CMake构build的可执行文件访问Boost DLL?

Linux上的boost和ssl客户端服务器构build问题

加强静态链接

不能用64位gcc在32位build立boost库

我只花了一两个小时来调查这个话题,所以决定发帖以防止别人浪费时间。

Windows不支持标准输入/输出句柄的IOCP。 当您通过GetStdHandle(STD_INPUT_HANDLE)处理句柄时,句柄没有设置FILE_FLAG_OVERLAPPED因此它不支持重叠(异步)IO。 但即使你

CreateFile(L"CONIN$",GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_FLAG_OVERLAPPED | FILE_FLAG_NO_BUFFERING,NULL);

WinAPI只是忽略dwFlagsAndAttributes并再次返回不支持重叠IO的句柄。 获得控制台输入/输出的异步IO的唯一方法是使用具有0超时的WaitForSingleObject的句柄,以便检查是否有任何内容读取非阻塞。 不完全异步IO,但可以避免多线程,如果这是一个目标。

有关控制台API的更多详细信息,请访问: https : //msdn.microsoft.com/en-us/library/ms686971(v=VS.85).aspx

GetStdHandle和CreateFile返回的句柄之间的区别在这里描述: https : GetStdHandle 。 简而言之,只有在CreateFile可以访问其控制台输入缓冲区时(即使它在父进程中被重定向),子进程之间的区别也是如此。

您需要调用io_service::run()来启动异步操作的事件处理循环。

class Example { public: Example( boost::asio::io_service& io_service ) : io_service(io_service),input_buffer( INPUT_BUFFER_LENGTH),input_handle( io_service) { } void start_reading(); void handle_read( const boost::system::error_code& error,std::size_t length); void handle_write( const boost::system::error_code& error); private: boost::asio::io_service& io_service; boost::asio::streambuf input_buffer; boost::asio::windows::stream_handle input_handle; }; int main( int argc,char * argv) { boost::asio::io_service io_service; Example obj( io_service ); obj.start_reading(); io_service.run(); return 0; }

您需要将您的stream_handle初始化为控制台输入句柄。 您不能使用相同的stream_handle输入和输出,因为这是两个不同的句柄。

对于输入:

Example() : /* ... */ input_handle( io_service,GetStdHandle(STD_INPUT_HANDLE) )

对于输出你可以使用CONSOLE_OUTPUT_HANDLE 。 但是,这可能是矫枉过正的,你不太可能将这么多的数据推送到窗口的标准输出,你需要使用异步写入。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐