Reputation: 199
I am using Indy UDP Server to read a string of data. However, I do not really know how to work with the Adata
parameter. I can get around it by converting it to binary by using the ByteToBin
function below and then convert it to hex by using BintoHex1
. But I really feel this is really stupid and it works really slow. Does anyone know how I can directly get the results without those two conversions?
Thanks!!
Here are the codes:
procedure TForm1.IdUDPServer1UDPRead(AThread: TIdUDPListenerThread;
const AData: TIdBytes; ABinding: TIdSocketHandle);
var
Buf: TIdBytes;
buffer: string;
Data_received: string;
begin
if bytestostring(AData) <> 'Hello' then
begin
buffer := HextoString('00');
SetLength(Buf, Length(buffer));
CopyTIdString(buffer, Buf, 0);
ABinding.SendTo(ABinding.PeerIP, ABinding.PeerPort, Buf);
Data_received := BinToHex1(ByteToBin(AData[1]) + ByteToBin(AData[2]) +
ByteToBin(AData[3]) + ByteToBin(AData[4]) + ByteToBin(AData[5]) +
ByteToBin(AData[6]) + ByteToBin(AData[7]) + ByteToBin(AData[8]) +
ByteToBin(AData[9]) + ByteToBin(AData[10]) + ByteToBin(AData[11]) +
ByteToBin(AData[12]));
end;
memo1.Lines.Add(Data_received);
Memo1.GoToTextEnd;
end;
function TForm1.ByteToBin(aByte: byte): String;
Const
c10: Array [Boolean] of Char = ('0', '1');
Var
eLoop1: byte;
Begin
SetLength(Result, 8);
For eLoop1 := 7 downto 0 do
Result[8 - eLoop1] := c10[(aByte and (1 shl eLoop1)) <> 0];
End;
function TForm1.BinToHex1(BinStr: string): string;
const
BinArray: array [0 .. 15, 0 .. 1] of string = (('0000', '0'), ('0001', '1'),
('0010', '2'), ('0011', '3'), ('0100', '4'), ('0101', '5'), ('0110', '6'),
('0111', '7'), ('1000', '8'), ('1001', '9'), ('1010', 'A'), ('1011', 'B'),
('1100', 'C'), ('1101', 'D'), ('1110', 'E'), ('1111', 'F'));
var
Error: Boolean;
j: Integer;
BinPart: string;
begin
Result := '';
Error := False;
for j := 1 to Length(BinStr) do
if not(BinStr[j] in ['0', '1']) then
begin
Error := True;
ShowMessage('This is not binary number');
Break;
end;
if not Error then
begin
case Length(BinStr) mod 4 of
1:
BinStr := '000' + BinStr;
2:
BinStr := '00' + BinStr;
3:
BinStr := '0' + BinStr;
end;
while Length(BinStr) > 0 do
begin
BinPart := Copy(BinStr, Length(BinStr) - 3, 4);
Delete(BinStr, Length(BinStr) - 3, 4);
for j := 1 to 16 do
if BinPart = BinArray[j - 1, 0] then
Result := BinArray[j - 1, 1] + Result;
end;
end;
end;
Upvotes: 2
Views: 6216
Reputation: 1224
You can also get the data as AnsiChars directly to a string by using SetString function like this:
var MyString: AnsiString;
SetString(MyString, PAnsiChar(@AData[0]), Length(AData));
However if you need HEX values, @Tom gave you the answer you need.
There are several functions to get Hex values already implemented in the Delphi itself, one is BinToHex mentioned in Tom's answer, then there's IntToHex where you can convert Integer or Byte values to Hex string, such as
// for int:
MyString:=IntToHex(integer, 2);
// or for byte:
MyString:=IntToHex(byte, 2);
// or for array of byte:
var MyArray: array of byte;
for i := 0 to Length(MyArray)-1 do
MyString:=MyString + ' ' + IntToHex(MyArray[i], 2);
// this adds all contents of MyArray to the string as Hex values, with space between each of them;
Depends what you actually need as result...
Upvotes: 2
Reputation: 596592
Your code is unnecessarily complex. Indy has many functions in its IdGlobal
unit for working with TIdBytes
data. For example, you can simplify your example to the following:
procedure TForm1.IdUDPServer1UDPRead(AThread: TIdUDPListenerThread;
const AData: TIdBytes; ABinding: TIdSocketHandle);
begin
if BytesToString(AData) <> 'Hello' then begin
ABinding.SendTo(ABinding.PeerIP, ABinding.PeerPort, ToBytes(Byte(0)));
end;
memo1.Lines.Add(ToHex(AData));
Memo1.GoToTextEnd;
end;
Upvotes: 4
Reputation: 21033
To convert AData to a string of hex characters, use the BinToHex function in the Classes unit.
var
MyHexString: string;
...
begin
SetLength(MyHexString, 2 * Length(AData)); // 2 * because one byte is represented by two characters
BinToHex(AData, @MyHexString[1], Length(AData));
...
end;
Upvotes: 2