Newsgroups : Borland : borland.public.delphi.internet.winsock : 2008 Mar : Re: How to limit number of concurrent clients in TServerSocket?
| Subject: | Re: How to limit number of concurrent clients in TServerSocket? |
| Posted by: | "Remy Lebeau (TeamB)" (no.spam@no.spam.com) |
| Date: | Wed, 26 Mar 2008 17:03:38 |
"Bo Berglund" <bo.berglund@telia.com> wrote in message
news:r2hlu39tkk03t6p2tn9k9aoomrl9evt7lp@4ax.com...
> When I try to close the socket inside the OnSocketEvent of the socket
> supplied by the server socket OnConnect it starts an eternal loop of
> calls to OnSocketEvent.
Because your code is still buggy. See below.
> My problem is that apparently the server is *not* operating "properly"
You are not using it properly in your code. Trust me, TServerSocket is very
stable, and has been for years. Problems that arise from it are almost
always caused by errors in the user's code that is using the component
incorrectly.
> The priority must be to get it to decrement the connections on disconnect.
The priority is to fix your code so the server can process disconnects
correctly in the first place.
> The handler assigns OnSocketEvent and OnSocketError handlers
> to the passed socket and also saves it in a local field variable FSocket.
DO NOT do that. You are overwritting TServerSocket's internal event
handlers that it assigns to each TCustomWinSocket object it creates. No
wonder your server is not working properly. You are not allowing
TServerSocket to react to disconnects, so it cannot fire the
OnClientDisconnect event or destroy the TCustomWinSocket object (which is
why the ActiveConnections count does not decrement). You need to use the
published events that TServerSocket itself exposes to you. Do not use the
TCustomWinSocket's events directly at all. You need to redesign your code
so your TClientComm class does not assign handlers to the TCustomWinSocket
events directly. For example:
procedure TRemoteServer.sckServerClientConnect(Sender: TObject; Socket:
TCustomWinSocket);
var
i: integer;
Comm: TClientComm;
begin
try
i := sckServer.Socket.ActiveConnections;
if i > 1 then
begin
Log('Connection attempted with client already connected.');
Socket.Close;
Exit;
end;
Log('Client connected, IP=' + Socket.RemoteAddress + ' Host=' +
Socket.RemoteHost);
Comm := TClientComm.Create(Socket, FRemoteServer);
try
FRemoteServer.ClientCallback := Comm.ClientCallback;
Log('Initializing new Client');
Comm.Initialize;
except
Comm.Free;
raise;
end;
Socket.Data := Comm;
Log('Socket communication channel opened to ' +
Socket.RemoteAddress + ' Host=' + Socket.RemoteHost);
except
on E: Exception do
Log('Exception during client connect: ' + E.Message);
end;
end;
procedure TRemoteServer.sckServerClientDisconnect(Sender: TObject;
Socket: TCustomWinSocket);
begin
if Socket.Data <> nil then
begin
TClientComm(Socket.Data).Disconnect;
FRemoteServer.ClientCallback := nil;
Log('Socket communication closed: ' + Socket.RemoteAddress);
end;
end;
procedure TRemoteServer.sckServerClientError(Sender: TObject; Socket:
TCustomWinSocket; ErrorEvent: TErrorEvent; var ErrorCode: Integer);
begin
// respond to the error as needed...
// use TClientComm(Socket.Data) as needed, if assigned...
end;
Gambit