我正在研究memcache协议的实现,在某些点上,它使用64位整数值.这些值必须以"网络字节顺序"存储.
我希望有一些uint64_t htonll(uint64_t value)
功能可以进行更改,但不幸的是,如果它存在,我找不到它.
所以我有1或2个问题:
我想到了一个基本的实现,但我不知道如何在编译时检查字节序以使代码可移植.所以你的帮助非常受欢迎;)
谢谢.
这是我写的最终解决方案,感谢Brian的解决方案.
uint64_t htonll(uint64_t value)
{
// The answer is 42
static const int num = 42;
// Check the endianness
if (*reinterpret_cast<const char*>(&num) == num)
{
const uint32_t high_part = htonl(static_cast<uint32_t>(value >> 32));
const uint32_t low_part = htonl(static_cast<uint32_t>(value & 0xFFFFFFFFLL));
return (static_cast<uint64_t>(low_part) << 32) | high_part;
} else
{
return value;
}
}
Run Code Online (Sandbox Code Playgroud) 我想x
通过套接字传递一个32位有符号整数.为了让接收器知道预期的字节顺序,我htonl(x)
在发送之前调用.htonl
期待一个,uint32_t
但我想确定当我把我int32_t
带到一个时会发生什么uint32_t
.
int32_t x = something;
uint32_t u = (uint32_t) x;
Run Code Online (Sandbox Code Playgroud)
总是这样的情况,每个字节x
和u
每个字节都完全相同吗?怎么回事:
uint32_t u = something;
int32_t x = (int32_t) u;
Run Code Online (Sandbox Code Playgroud)
我意识到负值会转换为大的无符号值,但这并不重要,因为我只是回到了另一端.但是,如果使用实际字节进行混乱,那么我无法确定返回将返回相同的值.
我开发网络应用程序并使用套接字API.
我想设置sockaddr_in6结构的sin6_addr字节顺序.
对于16位或32位变量,很简单:使用htons或htonl:
// IPv4
sockaddr_in addr;
addr.sin_port = htons(123);
addr.sin_addr.s_addr = htonl(123456);
Run Code Online (Sandbox Code Playgroud)
但对于128位变量,我不知道如何将字节顺序设置为网络字节顺序:
// IPv6
sockaddr_in6 addr;
addr.sin6_port = htons(123);
addr.sin6_addr.s6_addr = ??? // 16 bytes with network byte order but how to set?
Run Code Online (Sandbox Code Playgroud)
一些答案可能是使用htons 8次(2*8 = 16字节),或使用htonl 4次(4*4 = 16字节),但我不知道哪种方法是正确的.
谢谢.
据我所知,C库没有帮助将数值序列化为非文本字节流.如我错了请纠正我.
最常用的标准工具是htonl
POSIX等.这些功能有缺点:
用于将任意大小序列化为char
8位标准字节的接口将落在C标准之间,该标准不真正确认8位字节,并且无论标准(ITU?)将八位位组设置为基本传输单位.但旧的标准没有得到修订.
现在C11有许多可选组件,可以添加二进制序列化扩展以及线程之类的东西,而不需要对现有实现提出要求.
这样的扩展是否有用,或者担心非二进制补充机器是否毫无意义?
当我通过套接字将一个整数变量从一个进程发送到另一个进程,然后在接收端打印该值时,如果不使用ntohl/htonl,该值仍然相同,那么除了初始化套接字结构之外,我还需要使用这些函数.我理解litte/big endian.但是,当值保持不变时,为什么我们需要将端口和IP nos转换为主机/网络字节顺序.请详细解释整数是如何通过网络传输的?
我想通过网络发送一些双精度浮点数.(标准C,标准套接字)没有htond或ntohd将数据转换为网络字节顺序和从网络字节顺序转换数据.我该怎么办?我脑子里有几个解决方案,但我想知道常见的做法是什么.
(我也想知道发送64位整数的常见做法,比如gstreamer使用的gint64值)
编辑:这是我想到的一个解决方案.我认为它适用于任何大小的整数,但它是否适合双打?
void swap_if_necessary (void* buff, int buff_len)
{
uint32_t foo = 1;
if ( htonl(foo) != foo )
{
char* to_swap = (char*)buff;
int i;
for (i = 0; i < buff_len/2; i++)
{
char swap_buff = to_swap[i];
to_swap[i] = to_swap[buff_len -1 -i];
to_swap[buff_len -1 -i] = swap_buff;
}
}
}
Run Code Online (Sandbox Code Playgroud) cout << "Hello World !" << endl;
Run Code Online (Sandbox Code Playgroud)
对于我关于堆栈溢出的第一篇文章:我们什么时候应该使用该htonl
函数?我已经浏览了手册页。但是,我不太了解何时以及如何使用它。
Visual Studio的定义_byteswap_uint64
和_byteswap_ulong
在stdlib.h
。
我是否正确地假设,这不是标准的并且不会在 Linux 或 Darwin 上编译?
有没有办法以跨平台的方式定义这些包含?
我有一个变量
__be32 x;
Run Code Online (Sandbox Code Playgroud)
我有一个功能
__u32 foo(void){
__u32 a;
return a;
}
Run Code Online (Sandbox Code Playgroud)
我需要在变量中存储foo的返回值x
.
x=htonl(foo());
Run Code Online (Sandbox Code Playgroud)
这是对的吗?我有一个困惑是什么的返回类型ntohl()
和htonl()
.它们彼此相反吗?
要检查输出,我需要重新编译内核,我不想让我的系统出现任何错误.所以我在这里问.
htonl ×10
c ×5
endianness ×4
c++ ×2
portability ×2
sockets ×2
64-bit ×1
binaryfiles ×1
byte ×1
c# ×1
casting ×1
double ×1
include ×1
int ×1
linux-kernel ×1
networking ×1
unsigned ×1