在使用C++ MJPEG流服务器时,ASIO随机报头丢失

在使用C++ MJPEG流服务器时,ASIO随机报头丢失,c++,boost,thread-safety,boost-asio,mjpeg,C++,Boost,Thread Safety,Boost Asio,Mjpeg,我想我正面临一个boost::asio线程安全问题。让我解释一下: 背景: 我在Ubuntu 14.04上使用Boost1.68和G++4.8.4 我编写C++代码来制作MJPEG服务器。< /P> 以下是我的一些代码示例,其工作原理非常简单: 代码解释 1填写HTTP头 2以HandleMJPEG作为回调调用doWrite 3 doWrite使用HandleMJPEG作为回调调用async_write 4手册JPEG: 4.1将-JPEG边界添加到流中 4.2回调doWrite,再次调用Han

我想我正面临一个boost::asio线程安全问题。让我解释一下:

背景: 我在Ubuntu 14.04上使用Boost1.68和G++4.8.4

我编写C++代码来制作MJPEG服务器。< /P> 以下是我的一些代码示例,其工作原理非常简单:

代码解释 1填写HTTP头

2以HandleMJPEG作为回调调用doWrite

3 doWrite使用HandleMJPEG作为回调调用async_write

4手册JPEG:

4.1将-JPEG边界添加到流中

4.2回调doWrite,再次调用HandleMJPEG 4.3

实际代码 TL;博士 问题在于:这段代码90%的时间都在工作。有时,当我想在Firefox 66.0.3 Linux浏览器上查看流时,会出现一个下载弹出窗口,而不是显示图像

当我调查这些包时,似乎有一些标题缺失或拼写错误:

1/一切正常时

2/当它不好的时候


这就是为什么怀疑boost asio中存在线程安全问题的原因,但我不知道从何处查看…

您有悬而未决的参考。您的问题是std::bind

简介:当您有一个具有成员功能栏的类Foo时:

然后调用std::bind&Foo::bar,f,std::bind返回一个functor,它将f存储为副本

现在让我们回到您的代码:

doWrite(
    std::bind(&net::Reply::toBuffers, _reply),   // <---- [1]
    std::bind(&Connection::handleMJPEG, this),
    "'MJPEG Stream init header'");
在[2]中,toBuffer是从std::bind返回的函子的包装器。toBuffer是局部变量。在第[3]行中,您调用toBuffer,它返回常量缓冲区以获得一个_reply的副本-它不引用原始的_reply!异步写入立即返回[4]。doWrite结束,toBuffer被销毁,而由async_write启动的Boost lib机制中的某个地方的任务工作,它正在访问toBuffer返回的常量缓冲区——这里有悬空引用

调用bind时,您可以通过指针传递_reply-这样您将引用同一个_reply实例:

std::bind(&net::Reply::toBuffers, &_reply),

哇,谢谢你的充分解释^^事后看起来很明显,但我在这一点上被卡住了一段时间!非常感谢:-
doWrite(
    std::bind(&net::Reply::toBuffers, _reply),   // <---- [1]
    std::bind(&Connection::handleMJPEG, this),
    "'MJPEG Stream init header'");
void Connection::doWrite(
    std::function<std::vector<boost::asio::const_buffer>()> toBuffer, // [2]
    std::function<void()> callbackOnSuccess,
    const std::string& logInfo)
{

    auto self(shared_from_this());

    boost::asio::async_write(
        _socket, 
        toBuffer(), // [3]
        boost::asio::bind_executor( ....
        ...
    ));
    // [4]
}
std::bind(&net::Reply::toBuffers, &_reply),