通过UDP发送任何类型的数据

5

我已经尝试过到处搜索,但没有找到解决方案。以下是我的问题:

我有一个UDP socket,可以通过任何端口将数据发送到任何IP地址(已测试并确认正常工作)。

我阅读了许多教程,但他们都是操作char*[],没有说明如何解密。

我想要做的事情(伪代码):

客户端:

Class my_class;
send (..., my_class, sizeof(my_class),...)

服务器:

receive (sender, buffer, sizeof (buffer))
and do something like
Class my_class = (Class) buffer

我的服务器可以分析缓冲区的内容。

但是我在指针方面有些困惑,而且我只能发送char*[],所以我不知道如何进行前后转换。


1
阅读有关序列化的内容,由于您正在使用C++,因此Boost序列化库可能是一个不错的起点。 - PlasmaHH
1
由于您在使用指针方面感到困惑,为什么不考虑使用比C++更高级别的编程语言呢? - Oliver
顺便说一句,我想你会在终点重用对象,如果使用UDP,你需要自己确保数据的完整性,因为你无法保证发送的值就是接收到的值(最好使用TCP)。 - Pierre Lacave
2个回答

6
你不能只是“发送”你的类。你必须发送你的类数据的表示。同时,发送指向你的类的指针也不起作用。当网络上的另一个应用程序接收到你的指针时,它对他们来说毫无意义。
考虑以下内容:
class Data
{
  std::string  name_;
  unsigned value_;
} data;

你不能直接将“类”发送到网络中。如果你尝试这样做:

send(&data, sizeof(data));

你最终会向下游客户端发送无意义的内容。 value_ 可能会被正确接收,但 name_ 则肯定不会。这是因为 std::string 对象包含的远不止构成字符串的字符。还有计数器、指向数据缓冲区的指针以及谁知道还有什么其他东西。这些字符本身可能甚至不会在 (&data, &data[sizeof(data)]) 指示的内存空间中——这些字符将完全在其他地方。因此,在上述 send 伪代码中,你不仅会发送一堆客户端无法理解的东西,而且很多时候你甚至没有发送他们可以理解的内容。
进入 序列化。序列化只是意味着创建一个数据对象的表示形式,该表示形式可以存储、保存或发送到某个地方,并稍后重新组装。你决定这种序列化的形状。对于上面的 data,我们可以决定像这样进行序列化:
NNNNCCCCCCCC...VVVV

每个字符占用1字节,且:
  1. N是一个4位数字,表示ASCII格式下name_中的字符数
  2. C是N字节,每个字节都是name_中的一个字符
  3. V是一个4位无符号整数,表示ASCII格式下value_的值
将上述data序列化并发送的一种方法可能如下(警告:非生产质量,未经测试):
stringstream ss;
ss 
  << setw(4) << setfill('0') << right << data.name_.length() << setw(0)
  << data.name_
  << setw(4) << data.value_;

  string buf = ss.str();

  send(buf.c_str(), buf.length());

现在,我们不再尝试发送data,而是发送一个代表data的字符字符串。如果data是这样创建的:
data.name_ = "foo";
data.value_ = 42;

如果这样做,通过套接字发送的字符串将是:
0003foo0042

这可以被客户端接收并在客户端上重新组装成一个新的Data对象,该对象模仿了服务器端的内容。
我们使用的映射 - NNNNCCCCCCCC...VVVV - 必须被双方理解。这通常被称为通信协议
在所有应用程序领域中都有无数的协议和序列化方法。它们从超级简单的方法(如上面概述的方法)到高度压缩和复杂的方法(如FIX/FAST)。许多库提供序列化功能,满足各种应用程序的需求。Boost.Serialization值得一试,建议您研究一下。

这里只是简单地概括了一些内容,实际上还有很多需要注意的地方,比如字节序(Endianness), 安全性,会话控制等等。如果你要进行任何重要的网络编程,无论是客户端还是服务器端,你都需要做出很多学习努力。


1

您需要序列化您的类。这将转换为二进制表示形式,然后可以将其放入char*[]数据类型中并发送。 char * []实际上只是保存要发送的字节,因此您需要将类转换为字节。当它到达另一端时,您需要对其进行反序列化:将其从字节数组转换回对象。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接