简体   繁体   English

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

[英]Send any type of data over UDP

I tried searching everywhere but no luck. 我试着到处寻找但没有运气。 Here is my problem: 这是我的问题:

I have a UDP socket, which can send data to any IP address through any port (tested and confirmed working). 我有一个UDP套接字,它可以通过任何端口将数据发送到任何IP地址(经过测试和确认工作)。

I read many tutorials, but they were all manipulating char*[] , they did not specify how to decrypt it. 我阅读了很多教程,但是他们都在操作char*[] ,他们没有指定如何解密它。

What I would like to do (pseudo code): 我想做什么(伪代码):

Client: 客户:

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

Server: 服务器:

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

So I my server can analyze the content of the buffer. 所以我的服务器可以分析缓冲区的内容。

But I'm lost with pointers, and all I can send is char*[] , so I don't know how to convert back and forth. 但是我迷失了指针,我所能发送的只是char*[] ,所以我不知道如何来回转换。

You can't just "send" your class. 你不能只是“发送”你的课程。 You have to send a representation of the data in your class. 您必须在班级中发送数据的表示 And sending a pointer to your class won't work either. 并且向您的班级发送指针也不起作用。 When another application on the network receives your pointer, it will be meaningless to them. 当网络上的另一个应用程序收到您的指针时,它们将毫无意义。

Consider this: 考虑一下:

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

You can't just "send the class" down the wire. 你不能只是“发送课程”。 If you tried to do something like this: 如果您尝试执行以下操作:

send(&data, sizeof(data));

...you will end up sending nonsense to the downstream client. ...你最终会向下游客户端发送废话。 value_ might be received properly, but name_ surely won't. value_可能会被正确接收,但name_肯定不会。 This is because a std::string object consists of much more than just the characters that make up the string. 这是因为std::string对象不仅包含构成字符串的字符。 There are also counters, pointers to data buffers, and who knows what else. 还有计数器,指向数据缓冲区的指针,以及谁知道还有什么。 The characters themselves are probably not even going to be in the memory space indicated by (&data, &data[sizeof(data)]) -- those characters will be somewhere else entirely. 字符本身可能甚至不会出现在(&data, &data[sizeof(data)])指示的内存空间中 - 这些字符将完全位于其他地方。 So with the send psudocude above, not only do you send a bunch of stuff that the client can't understand, very often you don't even send what they can understand. 因此,使用上面的send psudocude,您不仅会发送一堆客户端无法理解的东西,通常您甚至不会发送他们可以理解的内容。

Enter serialization . 输入序列化 Serialization simply means creating a representation of your data object that can be stored, saved or sent someplace, and reassembled later. 序列化只是意味着创建数据对象的表示,可以存储,保存或发送到某个地方,并在以后重新组装。 You decide what shape this serialization will take. 您可以决定此序列化将采用的形状。 In the case of data above, we might decide to serialize like this: 对于上面的data ,我们可能会决定像这样序列化:

NNNNCCCCCCCC...VVVV

where each character is 1 byte, and: 每个字符为1个字节,并且:

  1. N is a 4 character integer, and is the number of characters in name_ in ASCII representation N是4个字符的整数,是ASCII表示中name_中的字符数
  2. C is N bytes, with each one being one character in name_ C是N个字节,每个字节在name_是一个字符
  3. V is a 4 character unsigned integer, and is the value in value_ in ASCII representation V是4个字符的无符号整数,是ASCII表示中value_的值

One way to serialize & send data above might be something like this (warning: not production quality, untested): 上面序列化和发送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());

Now, instead of trying to send data , we're sending a character string that represents data . 现在,我们不是尝试发送data ,而是发送一个表示data字符串。 If data was created like this: 如果data是这样创建的:

data.name_ = "foo";
data.value_ = 42;

...then the string that gets sent down the socket will be: ...然后从套接字发送的字符串将是:

0003foo0042

This can be received by the client and reassembled in to a new Data object on the client side that mimics what you have on the server side. 这可以由客户端接收并重新组装到客户端上的新Data对象,该对象模仿您在服务器端的内容。

The mapping we used above -- the NNNNCCCCCCCC...VVVV -- must be understood by both sides. 我们上面使用的映射NNNNCCCCCCCC...VVVV - 必须由双方理解。 This is often referred to as a communications protocol . 这通常被称为通信协议

There are countless protocols and serialization methods used across all application domains. 所有应用程序域都使用了无数的协议和序列化方法。 They range from the uber simplistic, like the one I outlined above, to highly compressed and complex, like FIX/FAST . 它们的范围很简单,就像上面概述的那样,高度压缩和复杂,如FIX / FAST Many libraries provide serialization capabilities that meet the needs of a wide range of applications. 许多库提供了可满足各种应用程序需求的序列化功能。 Boost.Serialization comes to mind, and I'd suggest you look in to that. 想到了Boost.Serialization ,我建议你研究一下。

There is much more to this that I've glossed over here. 我还有更多的东西在这里掩饰。 Things like Endianness , security, session control... If you are going to be doing any significant network programming, either on the client side or the server side, you've got quite a bit of learning ahead of you. 诸如Endianness ,安全性,会话控制......如果您要在客户端或服务器端进行任何重要的网络编程,那么您将获得相当多的学习经验。

You need to serialize your class. 你需要序列化你的课程。 This converts to a binary representation, which you can then put inside a char*[] data type and send. 这将转换为二进制表示,然后您可以将其放入char*[]数据类型并发送。 char*[] is really just holding bytes to send, so you need to convert your class into bytes. char * []实际上只是保存要发送的字节,因此您需要将类转换为字节。 When it arrives on the other side, you will need to deserialize it: convert it from an array of bytes back to an object. 当它到达另一侧时,您需要对其进行反序列化:将其从字节数组转换回对象。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM