Solved

Socket Connecting in OnError problem

Posted on 2004-10-21
1,474 Views
Last Modified: 2008-01-09
Need some advice...

When using the OnError event to catch errors on a TClientSocket, how
would one connect if the error was because the socket wasn't connecting?

procedure TForm1.ClientSocket1Error(Sender: TObject;
  Socket: TCustomWinSocket; ErrorEvent: TErrorEvent;
  var ErrorCode: Integer);
begin
  repeat
    Sleep(1000);
    TClientSocket(Socket).Active := True;
  until TClientSocket(Socket).Active;
end;


In the above, if the socket can't connect the second time Active is set
to true, the OnError is never fired.

Any tips on how to handle this?
0
Question by:EddieShipman
    8 Comments
     
    LVL 1

    Expert Comment

    by:sokpas
    I think you have to reconsider your error handling block.
    You have to decide prior to sending to the event handler routine if it is a connection error or not and retry connection outside the error handler, so the event can be retriggered.
    0
     
    LVL 26

    Author Comment

    by:EddieShipman
    You lost me  ;-(
    0
     
    LVL 1

    Accepted Solution

    by:
    Sorry for my bad english, :)
    After carefully reading again your question and the snippet, I see that you should change the error code to 0 to prevent the socket from raising an exception after successfully connecting. So

    procedure TForm1.ClientSocket1Error(Sender: TObject;
      Socket: TCustomWinSocket; ErrorEvent: TErrorEvent;
      var ErrorCode: Integer);
    begin
      repeat
        Sleep(1000);
        If Not TClientSocket(Socket).Active Then TClientSocket(Socket).open;
      until TClientSocket(Socket).Active;
      ErrorCode:=0;
    end;

    Alltrough you should add code for checking the ErrorEvent type if it was an eeConnect or not. Thus not trying to reconnect an allready open connection.
    0
     
    LVL 26

    Author Comment

    by:EddieShipman
    Nope, still not working.
    0
     
    LVL 1

    Expert Comment

    by:sokpas

    Then you must try this solution:

    You should not try to reconnect on the OnError event. In the connection part of your code you should do something like:

    ....
    Breakout:=False;
    RetriesCnt:=0;
    Repeat
        Socket.Open;
        If Not Socket.Active then
        begin
               Sleep(1000);
               Inc(RetriesCnt);
         end;
    Until Socket.Active or (RetriesCnt>10);
    .....
    0
     
    LVL 8

    Expert Comment

    by:gmayo
    The way I do it is to have a timer running which periodically checks the socket connection. If the socket has not connected, then it sets Active to true. If the OnError fires then the reconnecttimer is reset. In the extract below, OneCycle is called once per second.

    type
          TARSIF = class
          private
                ClientSocket : TClientSocket;
                SocketReconnectTime      : cardinal;
                ....
          end;


    procedure TARSIF.OnSocketError(Sender: TObject; Socket: TCustomWinSocket; ErrorEvent: TErrorEvent; var ErrorCode: Integer);
    begin
          ErrorCode := 0;
          SocketReconnectTime := GetTickCount + 5000;
    end;

    procedure TARSIF.OneCycle;
    var
          idx : integer;
    begin
          if (ClientSocket = nil) or (Assigned(ClientSocket) and (ClientSocket.Socket.Connected = false))
          and (GetTickCount >= SocketReconnectTime)
          then CreateSocket;
    end;

    procedure TARSIF.CreateSocket;
    begin
          if not Assigned(ClientSocket) then begin
                ClientSocket := TClientSocket.Create(fOwner);
                ClientSocket.Address := TheSDS.fConfig.ARSAddress;
                ClientSocket.Port := TheSDS.fConfig.ARSPort;
                ClientSocket.OnConnect := OnSocketConnect;
                ClientSocket.OnDisconnect := OnSocketDisconnect;
                ClientSocket.OnError := OnSocketError;
                ClientSocket.OnRead := OnSocketRead;
          end;
          if (ClientSocket.Address <> '') and (ClientSocket.Port <> 0) then ClientSocket.Active := true;
          SocketReconnectTime := GetTickCount + 5000;
    end;


    Geoff M.
    0
     
    LVL 26

    Author Comment

    by:EddieShipman
    Would this hog resources? What if the socket is disconnected between timer intervals and you try to read then. I'm having trouble calling a
    Connect in the OnError, if ther is another error, it never reenters the OnError.
    0
     
    LVL 8

    Expert Comment

    by:gmayo
    The socket won't read because it's disconnected. We use this for software which can run for days at a time - no problems. Bear in mind I haven't pasted the entire unit, so I might have missed one or two pertinent things... thinking about it I haven't pasted the OnDisconnect event which does some stuff. Can't do that til Monday now, sorry.

    I have tried to call the Connect in OnError and that *does* cause errors. I can't remember specifically, something like stack overflow or out of resources. Sockets are funny things - treat them with care. For example, you can't write to a socket whilst in an OnRead event. We do a lot of socket stuff, all with TClientSocket and TServerSocket, and these are things we've learnt the hard way over time. We can't use the newer stuff because of legacy software.

    Geoff M.
    0

    Write Comment

    Please enter a first name

    Please enter a last name

    We will never share this with anyone.

    Featured Post

    Do You Know the 4 Main Threat Actor Types?

    Do you know the main threat actor types? Most attackers fall into one of four categories, each with their own favored tactics, techniques, and procedures.

    Suggested Solutions

    A lot of questions regard threads in Delphi.   One of the more specific questions is how to show progress of the thread.   Updating a progressbar from inside a thread is a mistake. A solution to this would be to send a synchronized message to the…
    Creating an auto free TStringList The TStringList is a basic and frequently used object in Delphi. On many occasions, you may want to create a temporary list, process some items in the list and be done with the list. In such cases, you have to…
    This video Micro Tutorial is the first in a two-part series that shows how to create and use custom scanning profiles in Nuance's PaperPort 14.5 (http://www.experts-exchange.com/articles/17490/). But the ability to create custom scanning profiles al…
    Internet Business Fax to Email Made Easy - With eFax Corporate (http://www.enterprise.efax.com), you'll receive a dedicated online fax number, which is used the same way as a typical analog fax number. You'll receive secure faxes in your email, fr…

    884 members asked questions and received personalized solutions in the past 7 days.

    Join the community of 500,000 technology professionals and ask your questions.

    Join & Ask a Question

    Need Help in Real-Time?

    Connect with top rated Experts

    18 Experts available now in Live!

    Get 1:1 Help Now