首页 > 解决方案 > 客户端(javascript)无法使用 boost beast 和 opencv 从服务器接收图像或二进制文件

问题描述

我使用了 boost::beast Web 服务器异步的示例之一来使用 websocket 与客户端 javascript 进行通信。我正在尝试做简单的接收图像并将其写入服务器端。

我在服务器端收到的结果是损坏的 jpg 图像。先感谢您。

客户端(javascript)

var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
var img = document.getElementById("image");

var ws = null;
connect.onclick = function() {
   ws = new WebSocket(uri.value);
   ws.onopen = function(ev) {
     messages.innerText += "[connection opened]\n";
   };
   ws.onclose = function(ev) {
     messages.innerText += "[connection closed]\n";
   };
   ws.onmessage = function(ev) {
     messages.innerText += ev.data + "\n";
   };
   ws.onerror = function(ev) {
     messages.innerText += "[error]\n";
     console.log(ev);
   };
 };
disconnect.onclick = function() {
   ws.close();
};
send.onclick = function() {
   var canvas1 = ctx.getImageData(0,0,img.width,img.height);
   var binary = new Uint8Array(img.data.length);
   for (var i=0; i<img.data.length; ++i) {
     binary[i] = img.data[i];
   }

   ws.send(binary.buffer);
}

服务器端

void on_write(boost::system::error_code ec,
        std::size_t bytes_transferred)
{
   boost::ignore_unused(bytes_transferred);

   if(ec)
     return fail(ec, "write");

   buffer_.consume(buffer_.size());

   std::cout << "on write before do read\n";

   ws_.async_read(
            buffer_,
            boost::asio::bind_executor(
                strand_,
                std::bind(
                    &session::on_read,
                    shared_from_this(),
                    std::placeholders::_1,
                    std::placeholders::_2)));
   uint8_t *buf = new uint8_t [bytes_transferred];


boost::asio::buffer_copy(boost::asio::buffer(buf,bytes_transferred),buffer_.data(),bytes_transferred);
        ::cv::Mat mImg(400,320,CV_8UC3,buf);
        ::cv::imwrite("file.jpg",mImg);
      delete [] buf;

    }

标签: imageopencvwebsocketboost-beast

解决方案


我首先建议将您的代码重构为可测试的小函数。

写一个这样的函数:

template <class AsyncStream, class CompletionToken>
auto
async_write_opencv_image(AsyncStream&, CompletionToken&& token)
{
  // write composed op here
}

使用它,您可以将 aboost::beast::test::stream输入到函数中,该函数将允许您手动检查缓冲区以确保图像的正确性。

这样做的好处是现在您的图像编写代码与流无关,因此您可以将其换成任何其他类型。

如果您在这方面需要任何帮助,boost.org 上有大量文档以及 cpplang slack 团队的实时帮助。

编辑:

这是一个 wandbox 示例,如何可能还为 websockets 设置单元测试: https ://wandbox.org/permlink/EixDmotCphJwiDZ1


推荐阅读