【问题标题】:How to send a structure as data on UDP using SendBuffer?如何使用 SendBuffer 在 UDP 上将结构作为数据发送?
【发布时间】:2014-09-20 06:33:43
【问题描述】:
typedef struct
{
    char cStartByte;  // Set Cmd 0xB1
   int  iTotalBytes; 
   char cSeqNum;        // 0 to 99 repeating
   char cCommand;   //
   char cPrintCmd;  //
       float fData[8]
} CMD,*psCmdOut;

在代码中尝试了许多选项,但都没有成功,要放入什么??? sedn 上面的结构?

  UDPClient1->SendBuffer(EHost->Text,12000, ????);

【问题讨论】:

  • 我们怎么可能知道? UDPClient1 是什么? SendBuffer 到底做了什么??

标签: c++ borland-c++


【解决方案1】:

您不能使用套接字按原样发送您的结构:您需要serialize 它。你需要创建一个通用的数据交换格式,通常是一个char数组like this one

代码:

unsigned char* ToCharArray(psCmdOut s)
{
    unsigned char serial[12]; //32-bit arch
    serial[0] = s.cStartByte;
    /*etc.*/
    return serial;
}

您可以在(char*) 中来回转换您的结构,但我强烈建议您不要这样做:隐式转换隐藏了字节序、内部内存填充和对齐等细微之处,这可能会以不可预知的方式破坏您的系统。

【讨论】:

  • 这个建议在这种情况下是错误的。您不需要序列化结构,因为它只包含 POD 值。您可以将结构原样传递给send() 等套接字函数。在 Indy 的 SendBuffer() 的情况下,是否允许这样做取决于 Indy 版本。详情见我的回答。
【解决方案2】:

答案取决于您的 Indy 版本。

在 Indy 8 和 9 中,SendBuffer() 具有以下签名:

void __fastcall SendBuffer(String AHost, const int APort, void* ABuffer, const int AByteCount);

所以你可以这样做:

CMD cmd;
// fill cmd as needed...
UDPClient1->SendBuffer(EHost->Text, 12000, &cmd, sizeof(cmd));

在 Indy 10 中,SendBuffer() 改为采用 TIdBytes(动态字节数组):

void __fastcall SendBuffer(const String AHost, const TIdPort APort, const TIdBytes ABuffer);

所以你不能再直接传递结构指针了。但是,Indy 10 有一个 RawToBytes() 函数可以从内存块创建 TIdBytes,因此您可以这样做:

CMD cmd;
// fill cmd as needed...
UDPClient1->SendBuffer(EHost->Text, 12000, RawToBytes(&cmd, sizeof(cmd)));

【讨论】:

  • 非常有帮助的答案。你能用如何在服务器端接收结构的信息来完成它吗?
  • 这取决于您是在服务器端使用TIdUDPClient 还是TIdUDPServer(是的,TIdUDPClient 可以发送到另一个TIdUDPClient)。 TIdUDPClient 具有填充内存块或 TIdBytesReceiveBuffer() 方法,具体取决于 Indy 版本。 TIdUDPServer 有一个 OnUDPRead 事件,它使用 TStreamTIdBytes 提供数据,具体取决于 Indy 版本。 Indy 10 有一个BytesToRaw() 函数,用于将TIdBytes 复制到内存块中。
  • 首先:不应该是 sizeof(CMD) 而不是 sizeof(cmd) 吗?我尝试让它与 TIdUDPServer 一起工作,但无法做到。我打开了一个单独的问题,以免与这个问题脱节。也许你可以看看:link.
  • sizeof(a type)sizeof(variable of that type) 返回相同的值。
【解决方案3】:

正如@Sam 建议的那样:

UDPClient1->SendBuffer(EHost->Text,12000,reinterpret_cast(&cmd_command));

但结构的长度也是必需的。所以它会是:

UDPClient1->SendBuffer(EHost->Text,12000,reinterpret_cast<char*>(&cmd_command), sizeof(cmd_command));

而且我认为如果你通过添加来打包结构会更好

#pragma pack(1)

这将为您提供结构的实际大小。有了这个,您将能够发送完整的结构。在另一端接收时,将其类型转换回相同的结构。

【讨论】:

  • 并考虑字节序。并且永远不要在结构中添加交互。
  • 是的,也考虑字节序。
  • @LightnessRacesinOrbit:“永远不要在结构中添加交互”是什么意思?我没听懂。
  • 我的意思是写“间接”
  • 您不需要reinterpret_cast。在 SendBuffer() 接受指针的 Indy 版本中,指针被声明为 void*,因此您可以传递 &amp;cmd_command 而无需强制转换它。
猜你喜欢
  • 1970-01-01
  • 2022-01-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多