mia yazdı: ↑26 Ara 2017 05: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
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.