如何从网络管理双重的结束
我对这个问题的答案有一个大问题。 在c ++中交换双位的比特
然而,这个问题或多或少都是我搜索的:我从网络上收到一个双,我想在我的机器上正确编码。
在我收到int
的情况下,我使用ntohl
执行此代码:
int * piData = reinterpret_cast((void*)pData); //manage endianness of incomming network data unsigned long ulValue = ntohl(*piData); int iValue = static_cast(ulValue);
但是在我得到double
的情况下,我不知道该怎么做。
该问题的答案建议:
template void swap_endian(T& pX) { char& raw = reinterpret_cast(pX); std::reverse(&raw, &raw + sizeof(T)); }
但是,如果我引用此网站 :
The ntohl() function converts the unsigned integer netlong from network byte order to host byte order. When the two byte orders are different, this means the endian-ness of the data will be changed. When the two byte orders are the same, the data will not be changed.
相反,@ GManNickG对这个问题的回答总是用std::reverse
进行反演 。
考虑到这个答案是错误的,我错了吗? (在ntohl
使用的endianess的网络管理范围内虽然在OP问题的标题中没有准确说明)。
最后:我应该将我的double
分成4个字节的两个部分并在两个部分上应用ntohl
函数吗? 还有更多的经典解决方案吗?
在C中还有这个有趣的问题, 主机到网络加倍? ,但它限制为32位值。 答案说,由于架构差异,双打应该转换为字符串……我也会使用音频样本,我是否真的考虑将所有样本转换为数据库中的字符串? (双打来自我通过网络查询的数据库)
如果你的双打是IEEE 754格式,你应该相对没问题。 现在你必须将它们的64位分成两个32位,然后以big-endian顺序传输它们(这是网络顺序);
怎么样:
void send_double(double d) { long int i64 = *((reinterpret_cast)(&d)); /* Ugly, but works */ int hiword = htonl(static_cast (i64 >> 32)); send(hiword); int loword = htonl(static_cast (i64)); send(loword); } double recv_double() { int hiword = ntohl(recv_int()); int loword = ntohl(recv_int()); long int i64 = (((static_cast) hiword) << 32) | loword; return *((reinterpret_cast(&i64)); }
假设您有一个编译时选项来确定字节顺序:
#if BIG_ENDIAN template void swap_endian(T& pX) { // Don't need to do anything here... } #else template void swap_endian(T& pX) { char& raw = reinterpret_cast(pX); std::reverse(&raw, &raw + sizeof(T)); } #endif
当然,另一种选择是不要在网络上发送double
– 考虑到它不能保证与IEEE-754兼容 – 有些机器在那里使用其他浮点格式…例如使用一个字符串会起作用更好…
我无法让JohnKällén代码在我的机器上运行。 此外,将double转换为字节(8位,1个字符)可能更有用:
template string to_byte_string(const T& v) { char* begin_ = reinterpret_cast(v); return string(begin_, begin_ + sizeof(T)); } template T from_byte_string(std::string& s) { assert(s.size() == sizeof(T) && "Wrong Type Cast"); return *(reinterpret_cast(&s[0])); }
此代码也适用于使用POD类型的结构。
如果你真的想要双重作为两个整数
double d; int* data = reinterpret_cast(&d); int first = data[0]; int second = data[1];
最后, long int
并不总是64位整数(我必须使用long long int
int在我的机器上创建64位int)。