I have been working on wrapping ENet into a set of easy to use functions for a few weeks now and seem to have a bit of an issue.
I have a std::stringstream and am attempting to send the contents to a remote machine using ENet then reconstruct the std::stringstream on the remote machine.
The reason I need to use a std::stringstream is due to the fact that I'm serializing my data with the Cereal Serialization Library which requires a stream.
With Azoth's help he has identified that I need to be using std::istringstream and std::ostringstream. Previously I was only using std::stringstream which was causing an exception.
However now an exception is being thrown within Cereal at portable_binary.hpp line 156:
throw Exception("Failed to read " + std::to_string(size) + " bytes from input stream! Read " + std::to_string(readSize));
Here's what I'm doing:
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);
}
A Cereal Portable Binary Data Archive is constructed to hold a single vector. The std::ostringstream is sent off to the host using ENet.
This part seems to work okay, I can print the information out before and after and it appears to be the same, albeit some weird symbols, but they print out the same on both ends.
Now a std::istringstream is created on the host with the data we received.
NetPacket(enet_uint8 const* Data)
{
std::istringstream SData(reinterpret_cast<char const*>(Data));
{
cereal::PortableBinaryInputArchive Archive(SData);
Archive(PacketData);
}
}
At this point I receive the exception at line:
Archive(PacketData)
I have a feeling the data is being changed somehow when it's sent through ENet and/or I'm not pulling the data out of the std::ostringstream correctly and/or not putting the data back into the std::istringstream correctly.
Thank you very much for your time I greatly appreciate it.
Disclaimer: I'm not familiar with enet.
You are getting this error because you aren't constructing the std::stringstream properly upon receiving the packet. A send/receive pair should look something like:
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
}
And then on the receiving end, something like this:
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 );
}
}
The basic idea here: use cereal and some ostringstream to generate a string (which is really just an array of bytes), send those raw bytes over the network, pull them into an istringstream, and then have cereal parse that.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With