Отправка двоичных данных через веб-сокет beast (в C ++) - PullRequest
0 голосов
/ 26 декабря 2018

Я хочу отправить двоичные аудиоданные в службу 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?

Далее для отправки данных на веб-сокет наддува (после рукопожатия) я выполнил эту процедуру

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: Идут ли данныеправильно, как ожидалось?Как это проверить?(ожидается: См. эту ссылку )

Как происходит закрытие веб-сокета без отправки команды закрытия?

ОБНОВЛЕНИЕ:

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 голосов
/ 26 декабря 2018

Вы не можете использовать string для хранения двоичных данных, используйте char data[] с int length или std::vector<char> или любым другим.

Чтение двоичных данных не следует делать с getline(), как тольков двоичных файлах нет строк.

Вы можете использовать что-то вроде:

std::ifstream f("/home/rohan/TestFile.pcm", std::ios::binary);
std::vector<char> v(std::istreambuf_iterator<char>{f}, {});
0 голосов
/ 26 декабря 2018

Ответ 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

"При закрытиифрейм получен во время операции чтения, реализация автоматически ответит закрывающим фреймом и затем закроет основное соединение перед возвратом. В этом случае операция чтения завершится с кодом error :: 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, тогда я предлагаю вам поставить свой текущий проектна паузу и изучите Асио, чтобы вы могли эффективно использовать Зверя. В противном случае вы будете сталкиваться с препятствиями на каждом этапе пути.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...