EldoS | Feel safer!

Software components for data protection, secure storage and transfer

TElSocket Send Timeout

#29225
Posted: 04/11/2014 10:07:21
by Darian Miller (Standard support level)
Joined: 06/27/2011
Posts: 49

Delphi XE5/64-bit. When using TElSocket - what's the preferred way of setting a timeout on a Send method? Do I use SetSockOpt(NativeSocket, SO_SNDTIMEO, xx) .. directly?

I'm trying to chase down a stuck server and I have timeouts on connections and on some custom read routines, but don't see anything on Sends.
#29226
Posted: 04/11/2014 10:17:01
by Vsevolod Ievgiienko (Team)

Thank you for contacting us.

You can use TElSocket.CanSend method before Send is called to check if data can be sent.

As you have the source code, I recommend you to refer to TElCustomSimpleSSLClient.DoSend from SBSimpleSSL.pas for correct send with timeout implementation.
#29228
Posted: 04/11/2014 10:59:35
by Darian Miller (Standard support level)
Joined: 06/27/2011
Posts: 49

I'll take a look thanks, would suggest a simple SendWithTimeout() method added to TElSocket. (And a ReceiveWithTimeout)
#29229
Posted: 04/11/2014 11:38:26
by Eugene Mayevski (Team)

Well, that's exactly what CanSend and CanReceive do. I am not sure that we must bloat the API with the function which contains just one line of code, eg. if CanSend(timeout) then result := Send(...);


Sincerely yours
Eugene Mayevski
#29230
Posted: 04/11/2014 11:38:31
by Darian Miller (Standard support level)
Joined: 06/27/2011
Posts: 49

Ok - quick SocketHelper added for .SendWithTimeout that worked the first time tested. :)

Thanks


Code
  TElSocketHelper = class helper for TElSocket
  public
    function SendWithTimeout(const pBuffer:Pointer; const pSize:Integer; var pBytesSent:Integer; const pSendTimeoutMS:Integer):Integer;
  end;

const
  HELPER_READ_TIMEOUT = -2;
  HELPER_READ_ABORTED = -3;
  HELPER_LOST_CONNECTION = -4;
---


function TElSocketHelper.SendWithTimeout(const pBuffer:Pointer; const pSize:Integer; var pBytesSent:Integer; const pSendTimeoutMS:Integer):Integer;
var
  ToSend, Sent:Integer;
begin
  Result := 0;

  pBytesSent := 0;
  Sent := 0;
  ToSend := pSize;

  while (Result = 0) and (ToSend > 0) do
  begin
    try
      if State <> issConnected then
      begin
        Close(True);
        Result := HELPER_LOST_CONNECTION;
        Break;
      end;

      if pSendTimeoutMS > 0 then
      begin
        if not CanSend(pSendTimeoutMS) then
        begin
          Result := HELPER_READ_TIMEOUT;
          Break;
        end;
      end;

      Result := Send(Pointer(PtrUInt(pBuffer) + Cardinal(pSize - ToSend)), ToSend, Sent);
      if Result <> 0 then
      begin
        Result := HELPER_LOST_CONNECTION;
        Break;
      end;
      Dec(ToSend, Sent);
      Inc(pBytesSent, Sent);
    except
      on E : EElSocketError do
      begin
        Close(True);
        Result := HELPER_LOST_CONNECTION;
        Break;
      end;
    end;
  end;
end;
#29231
Posted: 04/11/2014 11:41:03
by Darian Miller (Standard support level)
Joined: 06/27/2011
Posts: 49

As far as a one-liner..

If CanSend(timeout) succeeds will .Send(data, BytesToSend, BytesSent) always send full BytesToSend?
#29232
Posted: 04/11/2014 11:49:34
by Eugene Mayevski (Team)

No, CanSend signals only that there's some available space in the outgoing buffers. Send() can always send less than you requested. Higher-level components such as TElSimpleSSLClient (which you can use in Passthrough mode BTW) handle this situation internally by calling Send in a loop.


Sincerely yours
Eugene Mayevski
#29233
Posted: 04/11/2014 12:22:49
by Darian Miller (Standard support level)
Joined: 06/27/2011
Posts: 49

Then a simple one-liner wouldn't suffice in this case. So I repeat my suggestion for a SendWithTimeout method. I've implemented a Class Helper to satisfy the needs at this point.
#29234
Posted: 04/11/2014 12:27:34
by Eugene Mayevski (Team)

And I suggest using TElSimpleSSLClient in this case :).


Sincerely yours
Eugene Mayevski

Reply

Statistics

Topic viewed 1060 times

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




|

Back to top

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

Got it!