{$IFDEF OS2}
{$Delphi+}
{$ENDIF}
{$I+}

Unit
  kSockCli;

Interface

Uses
{$IFDEF OS2}
  OS2Def,
  Os2Base,
{$ELSE}
  Windows,
  Os2Comp,
{$ENDIF}
  SysUtils,
  kSockets,
  kSockDef;

Const
  cRetries = 5;

Type
  tSockError = (seNoError, seHostNotFound, seUnblConnect);

  tSockClient = Class
  Protected
    fService: String;
    fHostname: String;
    Procedure ConnectSocket; Virtual;
    Procedure DisconnectSocket; Virtual;
    Function GetConnected: Boolean; Virtual;
    Procedure SetConnected (_Connected: Boolean); virtual;
    Function TransactLn (Const _In: String; Var _Out: String): Boolean; Virtual;
  Public
    fSocket: tSocket;
    Error: tSockError;
    Constructor Create;
    Destructor Destroy; override;
    Procedure Open; virtual;
    Procedure Close; virtual;
    Property Hostname: string read fHostname write fHostname;
    Property Service: string read fService write fService;
    Property Connected: boolean read GetConnected write SetConnected;
  End;

Implementation

Constructor tSockClient. Create;
Begin
  Inherited Create;
  fHostName := '';
  fSocket := tSocket. Create (AF_INET, SOCK_STREAM, IPPROTO_TCP);
  fSocket. Error := 0;
End;

Destructor tSockClient. Destroy;
Begin
  fSocket.Free;
  Inherited Destroy;
End;

Procedure tSockClient. ConnectSocket;
Var
  SAddr: tSockAddr;
  rc: ApiRet;
  Retries: integer;

Begin
  If fHostname = '' Then fSocket. Error := 11 Else
  Begin
    FillChar (SAddr, SizeOf (SAddr), #0);
    rc := fSocket. GetHostByName (fHostname);

    If rc = $FFFFFFFF Then fSocket. Error := 11 Else
    Begin
      SAddr. Sin_Addr. IPAddr := rc;
      SAddr. Sin_Port := fSocket. GetServPortByName (fService, 'tcp');
      SAddr. Sin_Family := AF_INET;
      Retries := cRetries;

      Repeat
        fSocket. Connect (SAddr);

        If fSocket. Error <> 0 Then
        Begin
          Dec (Retries);
          If Retries = 0 Then Exit;
        End;
      Until fSocket. isConnected;

    {$IFDEF OS2}
      fSocket. Blocking := False;
      fSocket. Error := 0;
    {$ENDIF}
    End;
  End;
End;

Procedure tSockClient. DisconnectSocket;
Begin
  fSocket. Close;
End;

Function tSockClient. GetConnected: Boolean;
Begin
  Result := fSocket.isConnected;
End;

Procedure tSockClient. SetConnected (_Connected: Boolean);
Begin
  If _Connected <> Connected Then
  Begin
    If Not Connected Then ConnectSocket Else DisconnectSocket;
  End;
End;

Procedure tSockClient.Open;
Begin
  Connected := True;
End;

Procedure tSockClient. Close;
Begin
  Connected := False;
End;

Function tSockClient. TransactLn (Const _In: String; Var _Out: String): Boolean;
Begin
  Result := fSocket. TransactStrLn (_In, _Out);
End;

End.