Рассмотрим следующую минимальную программу с использованием Borland 2007 и UDP-сервера и клиента Indy:
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 байта?
Во-вторых, что происходит с х и у?
Когда я изменяю тип данных t, x, y на short, я получаю:
sent 6
received 4
3 2 0
Оглядываясь вокруг, я обнаружил указатели на то, что упаковка (и, возможно, порядок байтов?) структуры имеет важное значение, однако я не смог найти четкого руководства по ее правильному проектированию.
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));
}