【问题标题】:Correctly sending and receiving a struct through Indy UDP通过 Indy UDP 正确发送和接收结构
【发布时间】:2015-01-21 04:38:51
【问题描述】:

考虑以下使用 Borland 2007 和 Indy UDP 服务器和客户端的最小程序:

struct DATA_PACKAGE
{
    int t;
    int x;
    int y;
};

void __fastcall TForm1::Button1Click(TObject *Sender)
{
   DATA_PACKAGE a;
   a.t = 3;
   a.x = 2;
   a.y = 1;
   Form1->Memo1->Lines->Add("sent " + IntToStr(sizeof(DATA_PACKAGE)));
   Form1->UDPClient1->SendBuffer(server,port,RawToBytes(&a, sizeof(DATA_PACKAGE)));
}

void __fastcall TForm1::UDPServer1UDPRead(TObject *Sender, TBytes AData,
      TIdSocketHandle *ABinding)
{
    DATA_PACKAGE r;
    Form1->Memo1->Lines->Add("received " + IntToStr(sizeof(AData)));
    BytesToRaw(AData, &r, sizeof(AData));
    Form1->Memo1->Lines->Add(IntToStr(r.t) + " " + IntToStr(r.x) + " " + IntToStr(r.y));
}

输出:

sent 12
received 4
3 4717901 0 

首先,为什么它发送了12个字节,却只接收了4个字节?

其次,x 和 y 发生了什么?

当我将 t,x,y 的数据类型更改为 short 时,我得到:

sent 6 
received 4 
3 2 0

环顾四周,我发现结构的打包(可能还有字节序?)很重要,但是我找不到如何正确设计它的明确指南。

【问题讨论】:

  • 接收到的数据取决于UDP通信的另一端。如果另一端像回显服务器一样工作,您可能希望收到与之前发送相同的数据。如果不知道另一方是如何工作的,就很难看出问题所在。
  • 如果我理解正确的话,你的意思是服务器端?该程序(出于测试目的)向自身发送数据,因为它是客户端和服务器合二为一。
  • sizeof(TBytes) 看起来很可疑。 TBytes 是什么?如果这是某个类,sizeof 可能会给出类本身的大小,而不是它包含的数据。
  • TBytesDyanmicArray<Byte> 的 typedef,即 Delphi 风格的动态字节数组。

标签: c++ udp indy


【解决方案1】:

TBytes 是一个动态字节数组,它由 RTL 作为指针实现,这就是为什么 sizeof(AData) 返回 4。不要使用 sizeof(AData),而是使用 AData.Length 属性:

void __fastcall TForm1::UDPServer1UDPRead(TObject *Sender, TBytes AData,
      TIdSocketHandle *ABinding)
{
    DATA_PACKAGE r;
    Form1->Memo1->Lines->Add("received " + IntToStr(AData.Length));
    BytesToRaw(AData, &r, AData.Length);
    Form1->Memo1->Lines->Add(IntToStr(r.t) + " " + IntToStr(r.x) + " " + IntToStr(r.y));
}

【讨论】:

  • 谢谢,这是个问题。只是为了澄清:如果我的结构包含动态对象(如 AnsiString 或向量),则事务不会以这种方式工作,对吧?
  • 没错。您不能通过套接字发送指针,您必须将数据序列化为扁平格式。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-07-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-24
  • 2017-02-23
  • 1970-01-01
相关资源
最近更新 更多