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

时间:2012-05-04 14:33:01

标签: c++ udp

我试着到处寻找但没有运气。这是我的问题:

我有一个UDP套接字,它可以通过任何端口将数据发送到任何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*[],所以我不知道如何来回转换。

2 个答案:

答案 0 :(得分:6)

你不能只是“发送”你的课程。您必须在班级中发送数据的表示。并且向您的班级发送指针也不起作用。当网络上的另一个应用程序收到你的指针时,它们将毫无意义。

考虑一下:

class Data
{
  std::string  name_;
  unsigned value_;
} data;

你不能只是“发送课程”。如果您尝试这样做:

send(&data, sizeof(data));

...您最终会向下游客户端发送废话。 value_可能会被正确收到,但name_肯定不会。这是因为std::string对象不仅包含构成字符串的字符。还有计数器,指向数据缓冲区的指针,以及谁知道还有什么。字符本身可能甚至不会出现在(&data, &data[sizeof(data)])指示的内存空间中 - 这些字符将完全位于其他地方。因此,使用上面的send psudocude,您不仅会发送一堆客户端无法理解的内容,通常您甚至不会发送可以理解的内容。

输入serialization。序列化只是意味着创建数据对象的表示,可以存储,保存或发送到某个地方,并在以后重新组装。您可以决定此序列化将采用的形状。在上面data的情况下,我们可能会决定像这样序列化:

NNNNCCCCCCCC...VVVV

其中每个字符为1个字节,并且:

  1. N是4个字符的整数,是ASCII表示中name_的字符数
  2. C是N个字节,每个字节都是name_
  3. 中的一个字符
  4. V是4个字符的无符号整数,是ASCII表示中的value_中的值
  5. 序列化的一种方法&上面发送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 - 必须由双方理解。这通常被称为communications protocol

    所有应用程序域都使用了无数的协议和序列化方法。它们的范围很简单,就像上面概述的那样,高度压缩和复杂,如FIX/FAST。许多库提供了可满足各种应用程序需求的序列化功能。 Boost.Serialization浮现在脑海中,我建议您留意一下。

    我还有更多的东西在这里掩饰。诸如Endianness之类的东西,安全性,会话控制......如果您要在客户端或服务器端进行任何重要的网络编程,那么您已经有了相当多的学习经验。

答案 1 :(得分:1)

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