通过野兽网络套接字发送二进制数据(在C ++中)

时间:2018-12-26 13:13:19

标签: c++ file-io websocket binaryfiles boost-beast

我想通过Websocket连接将二进制音频数据发送到IBM watson STT服务。我已成功建立连接,现在尝试以以下格式发送数据:

{
  "action":"start",
  "content-type": "audio/l16;rate=44100"
}
<binary audio data>
{
  "action":"stop"
}

为此:我正在读取原始音频文件(extn .pcm ),如下所示

#include <string>
#include <fstream>

ifstream fin;
string binarydata, bdataline;

fin.open("/home/rohan/TestFile.pcm", ios::binary | ios::in);

while (fin) {
    // Read a Line from File
    getline(fin, bdataline);
    binarydata = binarydata + bdataline;
}

问题1:我不确定我是否正确读取了二进制数据。 binarydata的数据类型应该为string吗?

接下来要在boost websocket上发送数据(握手后),我遵循了这个例程

void on_handshake(beast::error_code ec)
    {
         if(ec)
             return fail(ec, "handshake");

         // Send the Start message
         ws_.async_write(net::buffer("{\"action\":\"start\",\"content-type\": \"audio/l16;rate=44100\"}"), bind(&session::on_start, shared_from_this(), placeholders::_1));
    }

void on_start(beast::error_code ec)
    {
        if(ec)
            return fail(ec, "write:start");

        ws_.async_write(net::buffer(binarydata), bind(&session::on_binarysent, shared_from_this(), placeholders::_1));
    }

void on_binarysent(beast::error_code ec)
    {
        if(ec)
            return fail(ec, "write:Msg");

        ws_.async_write(net::buffer("{\"action\":\"stop\"}"), bind(&session::on_write, shared_from_this(), placeholders::_1));
    }


void on_write( beast::error_code ec) //,
    {
        if(ec)
            return fail(ec, "write:end");

        ws_.async_read(buffer_, bind(&session::on_start, shared_from_this(), placeholders::_1));
    }

程序不显示任何输出,并以

退出
  

write:start:WebSocket流在两个端点上均正常关闭

问题2:数据是否按预期正确运行?如何检查? (预期:See this link

如何在不发送关闭命令的情况下关闭websocket?

已更新

void on_start(beast::error_code ec)
    {
        if(ec)
            return fail(ec, "write:start");



ifstream infile("/home/rohan/TestFile.pcm", ios::in | ios::binary);
    streampos FileSize;

    if (infile) {
        // Get the size of the file
        infile.seekg(0, ios::end);
        FileSize = infile.tellg();
        infile.seekg(0, ios::beg);
    }
    char binarydata[(size_t)FileSize];
        ws_.binary(true);

        // Send binary data
        ws_.async_write(net::buffer(binarydata, sizeof(binarydata)), bind(&session::on_binarysent, shared_from_this(), placeholders::_1));
    }

2 个答案:

答案 0 :(得分:0)

答案1:

关于问题的websocket部分,您应确保通过调用websocket::stream::binary(true)发送二进制消息。参见:

https://www.boost.org/doc/libs/1_69_0/libs/beast/doc/html/beast/ref/boost__beast__websocket__stream/binary/overload1.html

答案2:

发件人:https://www.boost.org/doc/libs/1_69_0/libs/beast/doc/html/beast/using_websocket/control_frames.html#beast.using_websocket.control_frames.close_frames

“”在读取操作期间收到关闭帧时,实现将自动以关闭帧进行响应,然后在返回之前关闭基础连接。在这种情况下,读取操作将完成并显示代码错误:: closed。这向调用方表明连接已完全关闭。”

答案3 (已更新)

您写道:

vector<char> binarydata(istreambuf_iterator<char {infile}, {});

您正在使用局部变量作为异步操作的缓冲区。调用方负责确保缓冲区的生存期至少延长到调用完成处理程序之前。您的代码会产生未定义的行为。

Beast文档对此进行了明确说明:

“该库供熟悉Boost.Asio的程序员使用。希望使用异步接口的用户应该已经知道如何使用回调或协程创建并发网络程序。”

https://www.boost.org/doc/libs/1_69_0/libs/beast/doc/html/beast/introduction.html

如果您还不熟悉Asio,那么建议您暂停当前的项目并研究Asio,以便可以有效地使用Beast。否则,您会在路径的每一步遇到障碍。

答案 1 :(得分:-1)

您不能使用string来存储二进制数据,不能将char data[]int lengthstd::vector<char>或其他任何东西一起使用。

一旦二进制文件中没有行,就不应使用getline()来读取二进制数据。

您可以使用类似的内容:

std::ifstream f("/home/rohan/TestFile.pcm", std::ios::binary);
std::vector<char> v(std::istreambuf_iterator<char>{f}, {});