Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/joomla/2.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++ 使用async\u read\u时,boost::asio会截断输出吗?_C++_Boost_Boost Asio - Fatal编程技术网

C++ 使用async\u read\u时,boost::asio会截断输出吗?

C++ 使用async\u read\u时,boost::asio会截断输出吗?,c++,boost,boost-asio,C++,Boost,Boost Asio,这件事把我难住了 如果使用async\u read\u直到调用,那么打印出超过4k字节的内容似乎有问题 我有一个小功能,可以打印出100行(刚刚超过4k) 除了注册一个async\u read\u直到回调,在任何组合中都可以正常工作。在这一点上,我的输出被截断到大约4k。但请注意,并非总是如此,有时更少,有时整个内容都会打印出来,这似乎与机器上的负载有关,几乎像是有一些超时?一些asio线程的东西?无论如何,如果我注释掉async\u read\u,直到call,无论我调用printLines多

这件事把我难住了

如果使用
async\u read\u直到
调用,那么打印出超过4k字节的内容似乎有问题

我有一个小功能,可以打印出100行(刚刚超过4k)

除了注册一个
async\u read\u直到
回调,在任何组合中都可以正常工作。在这一点上,我的输出被截断到大约4k。但请注意,并非总是如此,有时更少,有时整个内容都会打印出来,这似乎与机器上的负载有关,几乎像是有一些超时?一些asio线程的东西?无论如何,如果我注释掉
async\u read\u,直到
call,无论我调用
printLines多少次,它都可以正常工作。我甚至可以使用
ioService
post
功能,它工作得很好

发生了什么事?顺便说一句,我正在使用linux和amd64机器gcc4.4。(红帽)


使用linux“strace”我得到了更多的线索:

似乎在调用async\u read\u之后,asio使用fcntl调用会导致输出文件描述符改变行为
它会在一段时间后停止打印输出:

选择(4[03],[],[],{300,0})=1(在[0]中,左{2988300000})
readv(0,[{“\n\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0”…,512}],1)=1
写下(2,“这是一个长句子的测试”…,93)=93
写下(2,“这是一个长句子的测试”…,93)=93
... 大约40次
写下(2,“这是一个长句子的测试”…,93)=53
写下(2,“这是一个长句子的测试”…,93)=-1 EAGAIN(资源暂时不可用)
写下(2,“这是一个长句子的测试”…,93)=-1 EAGAIN(资源暂时不可用)
写下(2,“这是一个长句子的测试”…,93)=-1 EAGAIN(资源暂时不可用)
写下(2,“这是一个长句子的测试”…,93)=-1 EAGAIN(资源暂时不可用)
写下(2,“这是一个长句子的测试”…,93)=-1 EAGAIN(资源暂时不可用)
... 剩余部分,直到达到100。

因此,您可以看到select循环正在等待我的输入返回键。然后我们叫我空的 读取处理程序并退出ioService。此时,我调用printLines函数并尝试打印100行,但在打印了40行之后,它就退出了

此EAGAIN的某些内容导致输出停止写入。
如果我在printf没有损坏之前不调用async\u read\u,请再次执行此操作。


我想我知道发生了什么,当我在标准数据文件描述符上请求异步读取模式时,似乎Asio正在将标准数据文件描述符转换为异步非阻塞模式。这就是为什么在一些输出之后,我会在写入时出现EAGAIN错误。当然printf会忽略这些,因此我的输出会被截断。不知道这是Asio中的一个bug还是linux上的一个副作用


下面是我复制问题的简单程序:

#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <iostream>

using namespace boost::asio;
using namespace std;

io_service ioService;
boost::asio::streambuf inStream;
posix::stream_descriptor input(ioService, STDIN_FILENO);

void printLines()
{
    for (int i = 0; i < 100; i++) {
        fprintf(stderr, "This is a test of a long sentence, there will be %d more sentences after this on is printed.\n", i);
    }
    fflush(stderr);
}

void readHandler(const boost::system::error_code& error)
{ // Don't care about read!! }

int main()
{
    boost::system::error_code ec;
    //printLines(); << this works if uncommented
    //ioService.post(printLines); << this works if uncommented

    boost::asio::async_read_until(input, inStream, "\n",
    bind(readHandler, placeholders::error)); // causes truncated output

    cout << "Hit Return to continue..." << endl;
    ioService.run_one( ec );
    assert(!ec);
    printLines(); // partial output if async_read_until is called?
    return 0;
}
#包括
#包括
#包括
使用名称空间boost::asio;
使用名称空间std;
io_服务ioService;
boost::asio::streambuf inStream;
posix::流描述符输入(ioService、标准数据文件号);
无效打印行()
{
对于(int i=0;i<100;i++){
fprintf(stderr,“这是对一个长句的测试,在打印此on后将有%d个句子。\n”,i);
}
fflush(stderr);
}
void readHandler(const boost::system::error\u代码和错误)
{//不在乎阅读!!}
int main()
{
boost::system::error_code ec;

//printLines();如果我在
printLines

int opt = 0;
ioctl( STDIN_FILENO, FIONBIO, &opt );
printLines();
这种行为是意料之中的

samm@macmini ~> ./a.out
Hit Return to continue...

This is a test of a long sentence, there will be 0 more sentences after this on is printed.
...
This is a test of a long sentence, there will be 96 more sentences after this on is printed.
This is a test of a long sentence, there will be 97 more sentences after this on is printed.
This is a test of a long sentence, there will be 98 more sentences after this on is printed.
This is a test of a long sentence, there will be 99 more sentences after this on is printed.
samm@macmini ~>
虽然我不清楚为什么会发生这种情况,但这可能是主要针对内核/设备的
ioctl
的副作用。在各种手册页上浏览时,我没有看到任何描述这种行为的内容。您可以尝试从
printLines
中使用
fprintf
切换到使用
posix::stream\u descriptor
改为
标准文件号


编辑:看起来已经有一些改进。Asio可以解决这种行为。特别是

  • 为添加了新的非_blocking()函数 管理服务器的非阻塞行为 套接字或描述符 io_control()命令名为 非阻塞io现在在中不推荐使用 支持这些新功能

  • 添加了新的本机\u非\u阻塞() 管理 底层网络的非阻塞模式 套接字或描述符。这些函数 旨在允许 任意函数的封装 非阻塞系统调用作为 异步操作 对系统的用户是透明的 套接字对象。函数没有 对动物行为的影响 套接字的同步操作 或描述符


看起来我很感兴趣。我在mac上使用了Boost 1.45来运行您的复制机,这些更改将出现在即将发布的Boost 1.47中。我将尝试获取Chris最新的asio开发版本,看看行为是否发生了变化。

您关于非阻塞stderr的理论是合理的。您是否看到在strace o中调用fcntl或ioctl来获取描述符2输出?我在RHEL 6系统上运行了您的复制机,我没有看到EAGAIN,但我确实看到了约60行后的截断输出。我确实注意到当将fprintf更改为std::cerr时,问题消失了。实际上我使用stderr只是为了强制刷新。我真的很有兴趣只使用标准的旧std::cout。实际上,我希望在将来只使用std::cout读取回调处理程序,但这就是它的启动方式。当我尝试在读取处理程序中打印回读取的内容时,它将截断我的输出。我需要某种方法来执行异步读取,但保持标准输出正常(阻塞).Chris使用管道在Asio中完成了很多异步工作,我想知道这是否会影响我的stdout?还有几个问题为什么要将stdin设置为ioctrl,为什么不设置stdout和le