Newsgroups : Borland : borland.public.delphi.internet.winsock : 2008 Mar : Re: How to limit number of concurrent clients in TServerSocket?

www.cryer.info
Managed Newsgroup Archive

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

Replies:

In response to:

www.cryer.info
Managed Newsgroup Archive