我正在使用WinSock将UDP数据包发送到服务器,我需要以big endian发送数据。我不确定如何在发送之前转换结构的字节顺序。
我有这样的结构:
struct ConnectIn
{
std::int64_t ConnectionID = 0x41727101980;
std::int32_t Action = 0;
std::int32_t TransactionID;
ConnectIn(std::int32_t transactionID)
{
TransactionID = transactionID;
}
};
此刻我正在这样发送:
ConnectIn msg(123);
int len = sizeof(msg);
int bytesSent = sendto(s, (char*)&msg, len, 0, (SOCKADDR*)&dest, sizeof(address));
如何在发送之前将msg
的字节顺序转换为大端?
如果您感到好奇,我发送的数据是Bit Torrent UDP tracker protocol。
答案 0 :(得分:4)
如果您想手动执行此操作,那么您所做的就是单独交换每个成员。您将成员从主机的字节顺序转换为网络的字节顺序。在Win32上htonll()
用于64位整数,htonl()
用于32位整数:
#include <Winsock2.h>
ConnectIn msg(123);
msg.ConnectionID = htonll(msg.ConnectionID);
msg.Action = htonl(msg.Action);
msg.TransactionID= htonl(msg.TransactionID);
然后,您可能还希望单独发送成员,以避免依赖主机系统的结构布局。 Windows ABI不会在此结构中插入任何填充,但也许对于您使用它的某些其他结构。所以这是基本的想法:
char buf[sizeof msg.ConnectionID + sizeof msg.Action + sizeof msg.TransactionID];
char *bufi = buf;
std::memcpy(bufi, &msg.ConnectionID, sizeof msg.ConnectionID);
bufi += sizeof msg.ConnectionID;
std::memcpy(bufi, &msg.Action, sizeof msg.Action);
bufi += sizeof msg.Action;
std::memcpy(bufi, &msg.TransactionID, sizeof msg.TransactionID);
bufi += sizeof msg.TransactionID;
int len = sizeof buf;
int bytesSent = sendto(s, buf, len, 0, (SOCKADDR*)&dest, sizeof(address));
然后在接收端,您使用64位和32位类型的相应ntoh*()
函数将网络的字节顺序转换为接收主机的字节顺序。< / p>
答案 1 :(得分:3)
是的,网络字节顺序(NBO)是Big Endian,因此您需要找到一种在Web上发送该结构的方法。
您目前正在做的事情不会发挥作用:您发送整个结构但接收器可能有不同的字节顺序,填充等等。
最简单的选择是:
对于第一个选项,有一些功能可以在Winsock2库中处理这些功能。这些是:
short
和unsigned
)short
和unsigned
)WSA功能略有不同,仅限Windows。
答案 2 :(得分:-1)
一个选项是单独转换每个数字
GCC:
int32_t __builtin_bswap32 (int32_t x)
int64_t __builtin_bswap64 (int64_t x)
对于MSVC:
unsigned short _byteswap_ushort(unsigned short value);
unsigned long _byteswap_ulong(unsigned long value);
unsigned __int64 _byteswap_uint64(unsigned __int64 value);