Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/windows/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何在Windows中使用boost asio从命令行异步读取输入?_C++_Windows_Boost_Boost Asio - Fatal编程技术网

C++ 如何在Windows中使用boost asio从命令行异步读取输入?

C++ 如何在Windows中使用boost asio从命令行异步读取输入?,c++,windows,boost,boost-asio,C++,Windows,Boost,Boost Asio,我发现它询问如何异步读取输入,但只适用于POSIX流描述符,这在Windows上不起作用。因此,我发现这表明我可以使用boost::asio::windows::stream\u句柄来代替POSIX流描述符 根据这两个示例,我得出了下面的代码。当我运行它时,我无法在命令提示符中键入任何内容,因为程序会立即终止。我希望它能够捕获用户的任何输入,可能会捕获到std::string,同时允许执行程序中的其他逻辑(即从Windows控制台执行异步I/O) 本质上,我试图避免在程序试图从stdin读取时阻

我发现它询问如何异步读取输入,但只适用于POSIX流描述符,这在Windows上不起作用。因此,我发现这表明我可以使用
boost::asio::windows::stream\u句柄来代替POSIX流描述符

根据这两个示例,我得出了下面的代码。当我运行它时,我无法在命令提示符中键入任何内容,因为程序会立即终止。我希望它能够捕获用户的任何输入,可能会捕获到
std::string
,同时允许执行程序中的其他逻辑(即从Windows控制台执行异步I/O)

本质上,我试图避免在程序试图从
stdin
读取时阻塞程序。我不知道这在Windows中是否可行,因为我还发现了其他用户在尝试执行相同操作时遇到的详细问题

#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, "\r\n",
                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, input_buffer, "\r\n",
           boost::bind( &Example::handle_read, this,
               boost::asio::placeholders::error,
               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, input_buffer, "\r\n",
           boost::bind( &Example::handle_read, this,
               boost::asio::placeholders::error,
               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;
}
#定义_WIN32_WINNT 0x0501
#定义输入缓冲区长度512
#包括
#包括
#为MinGW 4.5定义BOOST\u THREAD\u USE\u LIB//(https://svn.boost.org/trac/boost/ticket/4878)
#包括
#包括
课例{
公众:
示例(boost::asio::io_服务和io_服务)
:输入缓冲区(输入缓冲区长度)、输入句柄(io服务)
{
//读一行输入。
boost::asio::异步读取直到(输入句柄、输入缓冲区“\r\n”,
boost::bind(&示例::handle_read,this,
boost::asio::占位符::错误,
boost::asio::占位符::字节(已传输);
}
无效句柄读取(const boost::system::error\u code&error,std::size\u t length);
无效句柄写入(常量boost::system::error\u代码和错误);
私人:
boost::asio::streambuf输入缓冲区;
boost::asio::windows::stream\u handle输入\u handle;
};
无效示例::句柄读取(常量boost::系统::错误代码和错误,std::大小\u t长度)
{
如果(!错误)
{
//从输入中删除换行符。
输入缓冲区消耗(1);
输入缓冲区提交(长度-1);
std::istream是(&input_buffer);
std::字符串s;
是>>s;

std::cout您需要将流句柄初始化为控制台输入句柄。不能将同一个流句柄用于输入和输出,因为这是两个不同的句柄

输入:

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

对于输出,您将使用
CONSOLE\u output\u HANDLE
。但这可能有点过头了,您不太可能将需要使用异步写入的那么多数据推送到windows上的标准输出中。

您需要调用
io\u 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;
}

我只是花了一两个小时研究这个话题,所以决定发帖子,以防止其他人浪费时间

Windows不支持标准输入/输出句柄的IOCP。当您通过
GetStdHandle(STD\u input\u handle)
获取句柄时,句柄没有
FILE\u FLAG\u 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的唯一方法是将句柄与
WaitForSingleObject
一起使用,超时为0,这样您就可以检查是否存在非阻塞读取的内容。不完全是异步IO,但可以避免multith如果这是一个目标,就阅读

有关console API的更多详细信息:


这里描述了
GetStdHandle
返回的句柄与
CreateFile
返回的句柄之间的区别:。简言之,只有当
CreateFile
可以访问其控制台输入缓冲区时,才有区别。

我不是Windows用户,但不是我们e\r\n作为新行指示符?是的,但这会阻止它工作吗,因为\n仍在新行序列中?我将delimeter字符串更改为“\r\n”,结果相同。在哪里调用io_服务::run()?
io_服务.run()
不会在任何地方被调用,应该吗?正确的位置在哪里?我一定喜欢那些匿名的投票人。这是有道理的,但它会导致抛出一个异常-“分配:句柄无效”。此外,我需要根据MSDN将
控制台输入句柄
更改为
标准输入句柄
,以便将其编译。感谢您的帮助,山姆。我修改了上面的问题,以包含我现在拥有的完整代码。我合并了您的答案,但现在当我调用该程序时,它会立即返回并成功退出(没有崩溃)。当io_service.run()应该被阻止时,为什么它会返回?@nickb,因为您从未将句柄分配给任何东西,所以您无法从中读取。