Socket Connecting in OnError problem

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?
LVL 26
Eddie ShipmanAll-around developerAsked:
Who is Participating?

[Webinar] Streamline your web hosting managementRegister Today

x
 
sokpasConnect With a Mentor Commented:
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
 
sokpasCommented:
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
 
Eddie ShipmanAll-around developerAuthor Commented:
You lost me  ;-(
0
Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

 
Eddie ShipmanAll-around developerAuthor Commented:
Nope, still not working.
0
 
sokpasCommented:

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
 
gmayoCommented:
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
 
Eddie ShipmanAll-around developerAuthor Commented:
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
 
gmayoCommented:
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
All Courses

From novice to tech pro — start learning today.