在实现 UDP BitTorrent 跟踪器协议时,我注意到最常见的数据包解析步骤是检查前 64 位是否是协议 id
0x41727101980
,用于请求连接,然后再假设它是给出的连接 id 之一。
我意识到,当连接 id 只是用作唯一的位序列时,它的字节顺序并不重要,因此我有一个想法,就是不将其从网络字节顺序转换为主机,而只是按原样使用这些值,但是只有一个问题,所写的协议 id 与以大端编码的数据包中的协议 id 不匹配,除非代码在大端机器上运行,所以我必须始终在某个地方转换前 64 位。
我知道我可以在运行时转换该值一次,但也许有一些 hack 允许在
0x41727101980
中表达这个值 uint64_t
,这确保无论系统的字节序如何,它总是以大字节序编码?
我真正想知道的是是否相当于:
static uint64_t const PROTOCOL_ID = htobe64(0x41727101980);
在编译时是可能的。
BitTorrent 协议表示 “所有值均按网络字节顺序(大端)发送” 并针对连接请求显示此内容:
connect request:
Offset Size Name Value
0 64-bit integer protocol_id 0x41727101980 // magic constant
然后只需将最高有效字节放置在最小内存地址,直到将存储在最大内存地址的最低有效字节。
0xFF
删除第 8 位及以上。它可能看起来像这样:
#include <concepts>
#include <utility>
template <class T>
requires(std::unsigned_integral<T>)
constexpr T htobe(T val) {
return [val]<std::size_t... I>(std::index_sequence<I...>) {
return (... | ((val >> ((8 * (sizeof(T) - I - 1))) & 0xFF) << (8 * I)));
}(std::make_index_sequence<sizeof(T)>());
}
constexpr auto PROTOCOL_ID = htobe(0x41727101980u);
注意:这是假设您的系统上一个字节有 8 位。如果你想让它在其他系统上工作,你需要使用
CHAR_BIT
来调整位移位。