-1

Thank you for your help.

I am converting an older version of Delphi to XE5 and I am getting stuck with the Indy compnent. Need to use IdUDPClient.ReceiveBuffer

Here is my code:

while not Terminated do
begin
  try
    lenUDP:= IdUDPClient.ReceiveBuffer(myBuf, buffLength, -1 );
    if lenUDP<> 0 then
      Synchronize(ReceivedLine);
  except
    Terminate;
  end;
end;

where, myBuf = packed array [0 .. buffLength -1] of char;

All help is greatly appreciated.

Thank you,

Mike

MikeA
  • 19
  • 1
  • 2
  • And what is the problem you're having with the code you posted? You were told how to fix this for `SendBuffer` in your [previous question](http://stackoverflow.com/q/27129331). Apply the same changes here, replacing your `packed array [..] of char` with `TIdBytes`. (You can always take a quick look at the Indy source code, which would tell you what types were expected as parameters, instead of posting every single question here. Code Completion in the IDE also provides you with this information.) – Ken White Nov 25 '14 at 21:44
  • Ken, The above code is older and the component has changed. I tried to use TIdBytes but failed. I am not sure how to correctly implement TIdBytes. I will try your suggestion and see if replacing myBuf to TIdBytes. Not sure how to correctly set Length. Is this correct? myBuf: array of TIdBytes followed by setlegnth() OR myBuf: TIdBytes and then setLength? Thank you for your input. – MikeA Nov 25 '14 at 21:55
  • 2
    Yes. I realize the code has changed, but your question should indicate the specific problem you're having with porting the code. Also, this is the same basic information from your previous question, and the solution is based on the same changes. It's difficult for us when people ask questions, we answer them, and they make no effort to understand the answer and simply post another question. – Ken White Nov 25 '14 at 22:02
  • Ken, The question is how do I modernize the older code so that it will work? I must admit that I am out of my element and not familiar with the Indy components. I have attempted several iterations of the suggestion in the previous post but have been unsuccessful in achieving the desired outcome. I will continue to solve this issue. Thank you for your input. – MikeA Nov 25 '14 at 22:12
  • It seems to me that you are not aware that `char` has changed from `AnsiChar` to `WideChar`. Are you aware of that? – David Heffernan Nov 26 '14 at 07:29
  • David, Yes and no. I was aware of it when I had previously upgraded other code but had forgotten it. I did change the Strings to AnsiStrings. Thank you for the reminder. – MikeA Nov 26 '14 at 14:38

1 Answers1

5

As I told you in comments to your previous question:

You have to use a TIdBytes for that as well. Use SetLength() to pre-allocate it to the desired size, then call ReceiveBuffer() with it, and then you can copy out data from it as needed, either directly or with BytesToRaw().

For example:

private
  myBuf: TIdBytes;
...

while not Terminated do
begin
  try
    SetLength(myBuf, buffLength);
    lenUDP := IdUDPClient.ReceiveBuffer(myBuf, -1);
    if lenUDP > 0 then
    begin
      SetLength(myBuf, lenUDP);
      Synchronize(ReceivedLine);
    end;
  except
    Terminate;
  end;
end;

Since your original buffer was an array of Char, and your processing function is named ReceivedLine(), I am assuming your data is textual in nature. If that is true, you can use BytesToString() or (T|I)IdTextEncoding.GetString() to convert a TIdBytes to a String, if that is what ReceivedLine() uses myBuf for, eg:

S := BytesToString(myBuf{, en8bit});

S := BytesToString(myBuf, 0, lenUDP{, en8bit});

S := IndyTextEncoding_8bit.GetString(myBuf);

S := IndyTextEncoding_8bit.GetString(myBuf, 0, lenUDP);

You can use any charset encoding that Indy supports, either via the various en...(), Indy...Encoding(), or IndyTextEncoding...() functions in the IdGlobal unit, or the CharsetToEncoding() function in the IdGlobalProtocols unit.

UPDATE: since your buffer is part of a record with a union in it, you will have to use a local TIdBytes variable instead:

type
  myRecord = record
    ...
    myBuf: array[0..buffLength-1] of Byte;
    ...
  end;

...

private
  myRec: myRecord;

...

var
  udpBuf: TIdBytes;
...
SetLength(udpBuf, buffLength);
while not Terminated do
begin
  try
    lenUDP := IdUDPClient.ReceiveBuffer(udpBuf, -1);
    if lenUDP > 0 then
    begin
      BytesToRaw(udpBuf, myRec.myBuf[0], lenUDP);
      Synchronize(ReceivedLine);
    end;
  except
    Terminate;
  end;
end;
Community
  • 1
  • 1
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • Remy, myBuf is part of record that contains a Union 1: myBuf and 2: several variables of chars, words, and bytes. – MikeA Nov 26 '14 at 14:51
  • Then you will have to use a local `TIdBytes` variable and copy it into your record after reading. I updated my answer. – Remy Lebeau Nov 26 '14 at 17:23
  • Remy, In order to copy myBuf: TIdBytes to recvbuf is there a simpler way than: for I := 0 to 255 recvbuf[I] := BytesToChar(myBuf, I, nil); I have used SetLength(myBuf, 256) earlier. Where recvbuf is a packed array [0..256] of char. – MikeA Nov 26 '14 at 19:54
  • Use `BytesToRaw()` like I showed you, just adjust the *number* of bytes you tell it to copy, eg: `BytesToRaw(myBuf, recvbuf[0], (lenUDP div SizeOf(Char)) * SizeOf(Char));`. Remember, `SizeOf(Char)` is 2 in D2009+ but is 1 in earlier versions. And because of that difference, you have to be careful with `BytesToChar()` because it takes UTF-16 surrogates into account in D2009+. – Remy Lebeau Nov 26 '14 at 20:08