🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: borland.public.cppbuilder.internet.socket
Article #423

Re: Using TIdTCPServer

#423
From: Remy Lebeau (TeamB)
Date: Fri, 01 Feb 2008 21:33
127 lines
6116 bytes
"Peter" <piotrtrzeciak@yahoo.com> wrote in message 
news:47a369a7$1@newsgroups.borland.com...

> Shouldn't OnExecute be invoked only once per client connection?

No.  Most server code is written to loop its client handling, so the default 
behavior of OnExecute was designed to loop automatically for you so your 
handling code could be simplified.  This is also important for things like 
Indy's CommandHandlers, where the server has to handle the looping 
internally for you anyway, otherwise its internal handling breaks if you try 
to hook into it.  Also, in Indy 10, the connection handling is actually 
separated from the thread handling in order to support additional threading 
models (fibers, completion ports, etc), so you don't even have direct access 
to the actual thread anymore.

> 1. A clinet connects.
> 2. The listener thread spawns a new thred and executes OnExecute handler 
> in it.
> 3. Data exchange is performed within the OnExecute handler.
> 4. Either the client or the server closes the connection, and the thread 
> ends.
> 5. The listener thread spawns a NEW thread for a new connection.

All of that is exactly what TIdTCPServer actually does.  The only difference 
between what you understand and what Indy really does is in how #3 does its 
work.  Which do you think is easier for you:

1)
    procedure Execute(connection);
    begin
        while (not thread is terminated) and (connection is connected) do
        begin
            try
                repeat
                    read a command
                    process the command
                    send a reply
                until connection is disconnected;
            except
                disconnect connection
                terminate thread;
                exit;
            end;
        end;
    end;

2)
    procedure Execute(connection);
    begin
        read a command
        process the command
        send a reply
    end;

> As such, I assume there should be a clear OnConnect/OnExecute/OnDisconnect 
> sequence.

There already is, which is essentially as follows:

    try
        OnConnect;
        try
            repeat
                OnExecute;
            until Terminated;
        finally
            OnDisconnect;
        end;
    except
        Terminate;
    end

If you really want to do your own looping in OnExecute, you certainly can do 
that.  Simply disconnect the socket before exiting:

    procedure Execute()
    begin
        try
            while connected do
            begin
                read a command
                process the command
                send a reply
            end;
        finally
            disconnect
        end;
    end;

> If I'm coming into the OnExecute for the second time with the same 
> connection, how would I know where in the data I am?

Because you are supposed to exit the first OnExecute afte processing the 
first command, ready to process the next command when OnExecute is 
reentered, using the Data property of TIdPeerThread/TIdContext to persist 
any data you need between events (which you need to do anyway if you want to 
pass values between OnConnect/OnExecute/OnDisconnect.

> how would I force the connection to be dropped completely
> when at the end of the OnExecute method?

Just do so.  There is nothing stopping you from calling Disconnect() inside 
the OnExecute event.  The next time OnExecute is called, your 
reading/writing will raise an EIdConnClosedGracefully exception.  Simply 
allow that exception to escape back into the server (which you should be 
doing any EIdException-derived exception anyway) and it will release the 
socket and shut down the thread accordingly.

> the code inside of the if is always executed

Connected() can return true even if the socket is not actually connected 
anymore.  Most noticely, if there is still unread data in the connection's 
InputBuffer.  This is by design.

> I do not get the OnDisconnect handler every time.

OnDisconnect is not triggered until the thread is being shut down, whether 
the socket is still active or not.  That is the main reason why 
EIdException-derived exceptions must be allowed to reach the server's 
internal exception handlers, so it can track socket status correctly and 
manage the thread accordingly.  If you block the exceptions in your own 
exceptions handlers, the thread can continue to run endlessly until the 
server is deactivated.


Gambit 
Technical Details
Message-ID: <47a39006@newsgroups.borland.com>
Path: arc1-ca.pugleaf.net!g2news1.google.com!news2.google.com!news1.google.com!eweka.nl!lightspeed.eweka.nl!feeder1.cambrium.nl!feed.tweaknews.nl!news2.euro.net!newsfeed.freenet.de!newsfeed00.sul.t-online.de!newsfeed01.sul.t-online.de!t-online.de!newsgroups.borland.com!not-for-mail
References: <478e1c34$1@newsgroups.borland.com> <478e4760@newsgroups.borland.com> <4798a5e1$1@newsgroups.borland.com> <4798cf30$1@newsgroups.borland.com> <4798db8f$1@newsgroups.borland.com> <4798ef34$2@newsgroups.borland.com> <479e2c75$1@newsgroups.borland.com> <479e382e$1@newsgroups.borland.com> <479f4835$1@newsgroups.borland.com> <479f51f8$1@newsgroups.borland.com> <479f68b1$1@newsgroups.borland.com> <479f7070$1@newsgroups.borland.com> <479f9ae1$1@newsgroups.borland.com> <47a2265f$1@newsgroups.borland.com> <47a24592@newsgroups.borland.com> <47a369a7$1@newsgroups.borland.com>

Show Full Headers
Complete Article Headers
X-Google-Thread: 11508e,452e664b18b0b56c
X-Google-Attributes: gid11508e,public,usenet
X-Google-Language: ENGLISH,ASCII-7-bit
From: "Remy Lebeau \(TeamB\)" <no.spam@no.spam.com>
Newsgroups: borland.public.cppbuilder.internet.socket
References: <478e1c34$1@newsgroups.borland.com> <478e4760@newsgroups.borland.com> <4798a5e1$1@newsgroups.borland.com> <4798cf30$1@newsgroups.borland.com> <4798db8f$1@newsgroups.borland.com> <4798ef34$2@newsgroups.borland.com> <479e2c75$1@newsgroups.borland.com> <479e382e$1@newsgroups.borland.com> <479f4835$1@newsgroups.borland.com> <479f51f8$1@newsgroups.borland.com> <479f68b1$1@newsgroups.borland.com> <479f7070$1@newsgroups.borland.com> <479f9ae1$1@newsgroups.borland.com> <47a2265f$1@newsgroups.borland.com> <47a24592@newsgroups.borland.com> <47a369a7$1@newsgroups.borland.com>
Subject: Re: Using TIdTCPServer
Date: Fri, 1 Feb 2008 13:33:38 -0800
Lines: 129
Organization: Lebeau Software
X-Priority: 3
X-MSMail-Priority: Normal
X-Newsreader: Microsoft Outlook Express 6.00.2900.3138
X-RFC2646: Format=Flowed; Original
X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2900.3198
NNTP-Posting-Host: 207.178.157.90
Message-ID: <47a39006@newsgroups.borland.com>
X-Trace: newsgroups.borland.com 1201901574 207.178.157.90 (1 Feb 2008 13:32:54 -0700)
Path: arc1-ca.pugleaf.net!g2news1.google.com!news2.google.com!news1.google.com!eweka.nl!lightspeed.eweka.nl!feeder1.cambrium.nl!feed.tweaknews.nl!news2.euro.net!newsfeed.freenet.de!newsfeed00.sul.t-online.de!newsfeed01.sul.t-online.de!t-online.de!newsgroups.borland.com!not-for-mail