Alvin Lin
Alvin Lin

Reputation: 199

Indy UDP Read Contents of Adata

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

Answers (3)

That Marc
That Marc

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

Remy Lebeau
Remy Lebeau

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

Tom Brunberg
Tom Brunberg

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

Related Questions