tl;dr I am unable to read floats from a an istream created from a boost::streambuf which is filled using the boost asio UDP socket interface. The data I have appears corrupt or processed incorrectly.
I am currently writing an interface that will implement the DIS (Distributed Interactive Simulation) protocol. I am using the boost::asio libraries to open a UDP socket and to receive the data. I am pulling the data off the wire and into a streambuf correctly, but I am unable to read floats.
Code for socket:
boost::asio::streambuf streamBuf;
boost::asio::streambuf::mutable_buffers_type buf = streamBuf.prepare(maxSize);
udp::endpoint senderEndpoint;
size_t packetLength;
try {
packetLength = sock.receive_from(buf, senderEndpoint);
streamBuf.commit(packetLength);
} catch(boost::system::system_error se) {
std::cout << "ERROR: " << se.what() << std::endl;
}
std::istream stream(&streamBuf);
Code to read from istream
float readFloat32(std::istream& stream) {
float ret;
stream.read((char*)&ret, sizeof(float));
return ret;
}
double readFloat64(std::istream& stream) {
double ret;
stream.read((char*)&ret, sizeof(double));
return ret;
}
Now I have similar functions written for every data type I need (mostly uint8_t - uint32_t).
Parsing the PDU
//--Entity ID
entityState.entityID.siteID = readUInt16(stream);
entityState.entityID.appID = readUInt16(stream);
entityState.entityID.entityID = readUInt16(stream);
...etc, etc.
//--Entity Linear Velocity
entityState.entityLinearVelocity.x = readFloat32(stream);
entityState.entityLinearVelocity.y = readFloat32(stream);
entityState.entityLinearVelocity.z = readFloat32(stream);
...etc, etc.
The data I am trying to parse looks like the photo at the very end. I can parse everything just fine, but the when I get to the "Entity Linear Velocity" block which consists of 3 32-bit floating point numbers, my data become wrong. Using wireshark I have confirmed that the correct btyestream is being sent across the wire.
For the velocity I am sending this series of bytes:
42 74 aa 97 c2 80 b3 8f 42 e2 dc 54
Which equates to 61.166592,-64.350700 and 113.430328. However, my application reads this as
42 72 ffffffaa ffffff97 ffffffc2 ffffff80 ffffffb3 ffffff8f 42 ffffffe2 ffffffdc 54
And my floats end up being -1.10153e-24, -1.77004e-29, and 7.58951e+12.
Does anyone have any idea why I can read all sorts of various sizes of uints using this implementation, but the float fails to make any sense?
答案 0 :(得分:0)
这可能是由于结束问题。使用
进行测试时,以下类型的代码可以正常工作std::string bin = {'\x42', '\x74', '\xaa', '\x97'};
std::istringstream raw(bin);
使用byteswapping,即ntohl
,
float readFloat32(std::istream& stream) {
union {
float fval;
uint32_t ival;
} ret;
stream.read((char*)&ret, sizeof(float));
ret.ival = ntohl(ret.ival);
return ret.fval;
}
添加byteswapping后,readFloat
返回的值为61.1666
。