Отправка StringStream двоичных данных из Cereal с помощью ENet

Я работаю над упаковкой ENet в набор простых в использовании функций уже несколько недель, и, похоже, у меня возникли некоторые проблемы.

У меня есть std:: stringstream, и я пытаюсь отправить содержимое на удаленную машину с помощью ENet, а затем реконструировать std:: stringstream на удаленной машине.

Причина, по которой мне нужно использовать std:: stringstream, заключается в том, что я сериализую свои данные с помощью библиотеки Cereal Serialization, для которой требуется поток.

С помощью Азота он определил, что мне нужно использовать std:: istringstream и std::ostringstream. Ранее я использовал только std:: stringstream, который вызывал исключение.

Однако теперь в Cereal создается исключение в строке 156 portable_binary.hpp:

throw Exception("Failed to read " + std::to_string(size) + " bytes from input stream! Read " + std::to_string(readSize));

Вот что я делаю:

void Send(ENetHost* Host)
{
    std::ostringstream SData;
    {
        cereal::PortableBinaryOutputArchive Archive(SData);
        Archive(PacketData);
    }

    std::string Out = SData.str();

    ENetPacket* Packet = enet_packet_create(Out.c_str(), Out.size(), ENET_PACKET_FLAG_RELIABLE);
    enet_host_broadcast(Host, 0, Packet);
}

Портативный архив двоичных данных Cereal создан для хранения одного вектора. Std:: ostringstream отправляется на хост с помощью ENet.

Кажется, эта часть работает нормально, я могу распечатать информацию до и после, и она кажется одинаковой, хотя и с некоторыми странными символами, но они печатают одинаково на обоих концах.

Теперь на хосте создается std:: istringstream с данными, которые мы получили.

NetPacket(enet_uint8 const* Data)
{
    std::istringstream SData(reinterpret_cast<char const*>(Data));
    {
        cereal::PortableBinaryInputArchive Archive(SData);
        Archive(PacketData);
    }
}

В этот момент я получаю исключение в строке:

Archive(PacketData)

У меня такое ощущение, что данные каким-то образом меняются, когда они отправляются через ENet, и / или я неправильно извлекаю данные из std:: ostringstream и / или неправильно помещаю данные обратно в std:: istringstream.

Большое спасибо за ваше время, я очень ценю это.

1 ответ

Решение

Отказ от ответственности: я не знаком с enet.

Вы получаете эту ошибку, потому что вы не создаете std::stringstream правильно после получения пакета. Пара отправки / получения должна выглядеть примерно так:

my_send_function()
{
  std::ostringstream os;
  {    
    cereal::PortableBinaryOutputArchive ar(os);
    ar( whatever_needs_to_be_serialized );
  } // the binary archives will flush their output 
    // immediately, but it's better to
    // use cereal archives in an RAII matter all the time

  std::string data = os.str();

  create_packet(data.c_str(), data.size());
  // send out
}

А затем на приемном конце, что-то вроде этого:

my_receive_function( uint8_t const * data ) // data came from some packet
{
  MyDataType d;

  std::istringstream is(reinterpet_cast<char const *>(data));
  // this is safe to do since we generated the data using c_str(), which added
  // a null terminator to the data
  {
    cereal::PortableBinaryInputArchive ar(is);
    ar( d );
  }
}

Основная идея здесь: использовать cereal и некоторый ostringstream для генерации строки (которая на самом деле является просто массивом байтов), отправить эти необработанные байты по сети, перетащить их в поток istringstream, а затем проанализировать их.

Другие вопросы по тегам