发送固定大小的UDP数据包

时间:2018-10-11 19:36:53

标签: c++ visual-c++ udp

我正在编写一个C ++程序来发送10个字节的UDP数据包。 数据包包括3个部分:

1个字节-0-9之间的单个数字

1个字节-0到2之间的单个数字

8个字节-从0到uint64最大值的数字

比如说数字是2、0和14829735431805717965。 目前,我正在做的就是将这些数字作为变量发送到ostringstream,我从this thread读取后应该将值转换为ASCII以进行序列化。

ostringstream str1;
uint8_t byte1 = 2;
uint8_t byte2 = 0;
uint64_t bytes = 14829735431805717965;


str1 << byte1<< byte2 << bytes;
string result = str1.str();
const char *pchar = result.c_str();

上面的代码演示了使它与sendto()方法兼容的过程。但是,当我执行sizeof(str1)时,我得到152,甚至单独考虑这些变量的总和为10个字节(1 + 1 + 8)。当我做sizeof(result)sizeof(pchar)时,我分别得到28和4-没有什么比我的10个字节长。我只能弄清楚这样做的方法是错误的-uint64_t bytes的每个数字是否都转换为单独的ASCII,总计为150左右? 我到处寻找类似的问题,但无济于事。

1 个答案:

答案 0 :(得分:0)

  

但是当我执行sizeof(str1)时,我得到152

这是因为您正在获取ostringstream对象本身的字节大小。 ostringstream除了指向字符数据的指针外,还具有许多数据成员。您正在寻找实际字符数据的字节大小。 ostringstream不直接提供该大小。

  

甚至单独考虑这些变量的总和为10个字节(1 + 1 + 8)。

原始变量可以,是的。但是,通过使用operator<<,您将它们的值序列化为string,其中每个数字位都成为字符串中自己的字符,因此最终字符数据的总字节大小将更像22 ,而不是10。

  

当我执行sizeof(result)和sizeof(pchar)时,我分别得到28和4

同样,因为您正在获取string对象本身的字节大小(除了指向字符数据的指针之外,它还具有其他数据成员),以及原始指针本身的字节大小。您正在寻找string内部指向的字符数据的字节大小。

result.c_str()将返回一个指向实际字符数据的指针,而result.size()将为您提供该数据的正确字节大小。

  

我只能弄清楚我的方法不正确

在这种情况下,使用operator<<是完全错误的解决方案。要将 binary 数据放入ostream中,请改用其write()方法,例如:

uint8_t byte1 = 2;
uint8_t byte2 = 0;
uint64_t bytes = 14829735431805717965;

ostringstream str1;
str1.write(reinterpret_cast<char*>(&byte1), sizeof(byte1));
str1.write(reinterpret_cast<char*>(&byte2), sizeof(byte2));
str1.write(reinterpret_cast<char*>(&bytes), sizeof(bytes));

string result = str1.str();
sendto(..., result.c_str(), result.size(), ...);

我个人建议改用字节对齐的结构:

#pragma pack(push, 1)
struct packet {
    uint8_t byte1;
    uint8_t byte2;
    uint64_t bytes;
};
#pragma pack(pop)

packet p;
p.byte1 = 2;
p.byte2 = 0;
p.bytes = 14829735431805717965;

sendto(..., reinterpret_cast<char*>(&packet), sizeof(packet), ...);

或者,更糟糕的是,只需使用一个简单的字节数组:

char packet[10];

uint8_t byte1 = 2;
uint8_t byte2 = 0;
uint64_t bytes = 14829735431805717965;

memcpy(&packet[0], &byte1, sizeof(byte1));
memcpy(&packet[1], &byte2, sizeof(byte2));
memcpy(&packet[2], &bytes, sizeof(bytes));
/* or:
*reinterpret_cast<uint8_t*>(&packet[0]) = byte1;
*reinterpret_cast<uint8_t*>(&packet[1]) = byte2;
*reinterpret_cast<uint64_t*>(&packet[2]) = bytes;
*/

sendto(..., packet, sizeof(packet), ...);