EldoS | Feel safer!

Software components for data protection, secure storage and transfer

TElSocket Read with size + timeout?

Also by EldoS: CallbackRegistry
A component to monitor and control Windows registry access and create virtual registry keys.
#22067
Posted: 10/17/2012 17:13:12
by Darian Miller (Standard support level)
Joined: 06/27/2011
Posts: 48

Is there a recommended implementation for a basic TELSocket to read a specific number of bytes within a given timeout period?

I'd like to say something like:
Code
Procedure ReadSomething();
const
  ReadTimeOut = 5000;
  BytesToRead = 100;
var
  ByteBuffer:TBytes;
  SocketResult:Integer;
begin
  SocketResult := Socket.ReadTimeout(ByteBuffer, BytesToRead, ReadTimeOut);
  if SocketResult = 0 then
  begin
    DoSomething(ByteBuffer);  //ByteBuffer guaranteed to be exactly BytesToRead in length
  end
  else
    ShowMessage('Failed To Read, error ' + IntToStr(SocketResult));
end;  



It appears that if something like this is called, that it will block until the bytes are received, or the connection is lost (as it basically calls a socket RECV() method)

Code
if Socket.CanReceive(ReadTimeOut) then
begin
  SocketResult := Socket.Receive(ByteBuffer, BytesToRead, BytesRead);
end;


After a CanReceive() is there a way to determine the number of bytes available? If so, then a loop can be created to extract from the receive buffer until the length desired or until the timeout period is achieved.


Thanks for any input.
#22068
Posted: 10/17/2012 17:27:19
by Darian Miller (Standard support level)
Joined: 06/27/2011
Posts: 48

Looks like my assumption on RECV was incorrect. It receives as much as currently available, up to the buffer size given. (Which appears to be 16,384 in this case)

So it's a loop of CanReceive(ReadTimeout) and Receive(Buffer, SizeDesired, BytesReceived)... and the loop exits when enough bytes received or timeout is hit.
#22069
Posted: 10/17/2012 18:37:35
by Darian Miller (Standard support level)
Joined: 06/27/2011
Posts: 48

Quick solution for Delphi using a Class Helper: (Available in Delphi 2006+)

Code
  TElSocketHelper = class helper for TElSocket
  public
    function ReceiveWithTimeout(var pDestination:TBytes; const pBytesToRead:Integer; const pReadTimeoutMS:Integer):Integer;
  end;

  const
    HELPER_READ_TIMEOUT = -2;



Similar to Socket.Receive(), use Socket.ReceiveWithTimeout() instead to specify a read timeout.


Code
function TElSocketHelper.ReceiveWithTimeout(var pDestination:TBytes; const pBytesToRead:Integer; const pReadTimeoutMS:Integer):Integer;
const
  DEF_BUFFER_SIZE = 16384;
var
  vReadBuffer:TBytes;
  vMaxToReceive:Integer;
  vActualReceived:Integer;
  vTotalReceived:Integer;
begin
  Result := 0;
  vTotalReceived := 0;
  SetLength(vReadBuffer, DEF_BUFFER_SIZE);

  while (Result = 0) and (pBytesToRead - vTotalReceived > 0) do
  begin
    if CanReceive(pReadTimeoutMS) then
    begin
      //We're 'still-alive', note that timeout is from time of last activity
      vMaxToReceive := Min(Length(vReadBuffer), pBytesToRead - vTotalReceived);
      Result := Receive(vReadBuffer, vMaxToReceive, vActualReceived);
      if Result = 0 then
      begin
        AppendBytes(vReadBuffer, pDestination, vActualReceived);
        Inc(vTotalReceived, vActualReceived);
      end;
    end
    else
    begin
      Result := HELPER_READ_TIMEOUT;
    end;
  end;
end;
#22075
Posted: 10/18/2012 00:19:29
by Vsevolod Ievgiienko (EldoS Corp.)

Hello, Darian. Thank you for sharing your code.

Do I understand you right that your problem is solved?

Reply

Statistics

Topic viewed 729 times

Number of guests: 1, registered members: 0, in total hidden: 0




|

Back to top

As of July 15, 2016 EldoS Corporation will operate as a division of /n software inc. For more information, please read the announcement.

Got it!