how to add / extract header from tidbytes ?

Delphi'de kod yazma ile ilgili sorularınızı bu foruma yazabilirsiniz.
Cevapla
Kullanıcı avatarı
mia
Üye
Mesajlar: 239
Kayıt: 17 Nis 2015 01:18

how to add / extract header from tidbytes ?

Mesaj gönderen mia » 26 Ara 2017 02:35

i have this current tidbytes variable

Kod: Tümünü seç

var
BufferChannel : tidbyets;
...
BufferChannel:= RawToBytes('Buffer^, Buffersize);
udpreciver.SendBuffer(ipaddr, port, BufferChannel);
which i send it through indy udp server as sendbuffer

i want to add extra data with it while sending like adding header infront of bufferchannel and extract this data in server side

something like this

Kod: Tümünü seç

type
  THeader = packed record
    Channelname: string;
    Channelnumber: integer;
  end; 
but i couldn't manage the code to insert the record in the BufferChannel Variable
بِسْمِ اللهِ الرَّحْمنِ الرَّحِيمِ
in god i trust with every movement i do
graduated student and looking for knowledge

Kullanıcı avatarı
SimaWB
Üye
Mesajlar: 1292
Kayıt: 07 May 2009 09:42
Konum: İstanbul
İletişim:

Re: how to add / extract header from tidbytes ?

Mesaj gönderen SimaWB » 26 Ara 2017 02:59

You can use Move procedure. Like this:

Kod: Tümünü seç

var
  NewBuffer: TIdBytes;
  header: THeader;
 begin
   SetLength(NewBuffer, Length(BufferChannel) + Length(header.Channelname) + SizeOf(header.Channelnumber));
   Move(BufferChannel[0], NewBuffer[0], Length(NewBuffer));
Then send NewBuffer...
There's no place like 127.0.0.1

Kullanıcı avatarı
mia
Üye
Mesajlar: 239
Kayıt: 17 Nis 2015 01:18

Re: how to add / extract header from tidbytes ?

Mesaj gönderen mia » 26 Ara 2017 04:31

but how to extract that header in server side ? and cut it out from the actual bufferchannel ?
بِسْمِ اللهِ الرَّحْمنِ الرَّحِيمِ
in god i trust with every movement i do
graduated student and looking for knowledge

Kullanıcı avatarı
SimaWB
Üye
Mesajlar: 1292
Kayıt: 07 May 2009 09:42
Konum: İstanbul
İletişim:

Re: how to add / extract header from tidbytes ?

Mesaj gönderen SimaWB » 26 Ara 2017 09:28

if you use string then you have to send the length of this string to another side. So; may be your THeader type should be like this:

Kod: Tümünü seç

THeader = packed record
  ChannelnameLength: Integer;
  Channelname: string;
  Channelnumber: integer;
end; 
There's no place like 127.0.0.1

ertank
Üye
Mesajlar: 1111
Kayıt: 11 Eyl 2015 11:45

Re: how to add / extract header from tidbytes ?

Mesaj gönderen ertank » 01 Oca 2018 10:05

mia yazdı:
26 Ara 2017 04:31
but how to extract that header in server side ? and cut it out from the actual bufferchannel ?
If you have string inside of a structure, I strongly suggest you do not depend on Length() information. As Length() gives characters in string however memory footprint of that string might be bigger. If you are using Delphi 2009 or later that size is mostly double the length.

It is already suggested you to use TCP protocol and not UDP. Main reason was that you will never know packet arrived to destination. If data you are transmitting is larger than a single data packet you maybe in big trouble using UDP protocol.

Coming to your question. Basically, you have to do below;
1- You need to add size of THeader information in your data.
2- You need to add THeader information itself in your data.
3- You need to add your real buffer to send in your data.

Since you are dealing with strings and probably unicode. I suggest you use json strings to serialize your record structure and then convert that json string into bytes using UTF-8 encoding. That will ensure you that receiving party will display correct national characters on the other side of the transmission.

I myself prefer mORMot framework if I need to do something with json. It is free and you can download latest sources from below link:
Homepage: https://synopse.info/fossil/wiki/Synopse+OpenSource
Download link: https://synopse.info/files/mORMotNightlyBuild.zip

For following example it is enough that you only add main directory of the extracted archive in your Delphi library search path.

Your record structure should contain "packed" word if you are to use mORMot framework.

Kod: Tümünü seç

type
  THeader = packed record
    Channelname: string;
    Channelnumber: integer;
  end;
You should include

Kod: Tümünü seç

uses
  SynCommons;
At this point you are ready to use the framework in your code.

In order to send your data and THeader record inserted at the beginning of it, you can use a code like below:

Kod: Tümünü seç

var
  MyRec: THeader;
  RecOverhead: Int32;
  Converter: array [0..3] of Byte absolute RecOverhead;
  RecordBuffer: TIdBytes;
  RestOfTheData: TIdBytes;
  FinalBuffer: TIdBytes;
  SerializedData: RawUTF8;  // RawUTF8 is a type defined in SynCommons unit
  I: Integer;
begin
  MyRec.Channelname := 'test string to send. Can contain national letters ÜĞİŞÇÖ';
  MyRec.Channelnumber := 5;

  // Serialize record info json string
  SerializedData := SaveJSON(MyRec, TypeInfo(THeader));
  // save json string in TIdBytes
  RecordBuffer := ToBytes(string(SerializedData), IndyTextEncoding_UTF8);
  // get length of TIdBytes
  RecOverhead := Length(RecordBuffer);

  SetLength(RestOfTheData, 10);
  for I := 0 to 9 do RestOfTheData[I] := I; // fill buffer up with something

  SetLength(FinalBuffer, 4);
  Move(Converter[0], FinalBuffer[0], 4); // Length of THeader information finishes here
  InsertBytes(FinalBuffer, 4, RecordBuffer);  // THeader information itself
  InsertBytes(FinalBuffer, 4+RecOverhead, RestOfTheData); // Any buffer you want to send

  IdUDPClient1.SendBuffer(FinalBuffer);
end;
On the receiving side you should have a TIdUDPServer component and its OnUDPRead() event should look like below in order to receive THeader record and data

Kod: Tümünü seç

procedure TForm1.IdUDPServer1UDPRead(AThread: TIdUDPListenerThread;
  const AData: TIdBytes; ABinding: TIdSocketHandle);
var
  ReadRecord: THeader;
  SerializedRecord: RawUTF8;
  TempBuf: TIdBytes;
  DataBuffer: TBytes;
  Converter: array[0..4] of Byte;
  HeaderOverhead: Int32 absolute Converter;
begin
  Move(AData[0], Converter[0], 4); // We now have length of THeader data

  // Get back information into our record structure
  SetLength(TempBuf, HeaderOverhead);
  Move(AData[4], TempBuf[0], HeaderOverHead); // Get TIdBytes data of THeader record
  SerializedRecord := RawUTF8(BytesToString(TempBuf, IndyTextEncoding_UTF8));  // Get serialized RawUTF8 string of THeader record
  RecordLoadJSON(ReadRecord, SerializedRecord, TypeInfo(THeader));  // Deserialize THeader record

  // Read remaining received data
  SetLength(DataBuffer, Length(AData) - 4 - HeaderOverHead);
  Move(AData[4 + HeaderOverHead], DataBuffer[0], Length(DataBuffer));

  // Here you have your THeader record and DataBuffer received and ready to use
end;
Attached is a Delphi 10.2.2 project. As to my tests it is working fine on my system.
Dosya ekleri
IdUDPClient send and receive record in buffer.7z
(6 KiB) 10 kere indirildi

Cevapla