Board index » delphi » TCPServer that does not destroy its TIdTCPConnections

TCPServer that does not destroy its TIdTCPConnections


2005-01-16 06:39:41 PM
delphi120
Hi all, I'd appretiate an advise:
I need to develop a TCP Server that does not free (nor disconnect) the
socket connection it made with the client, eventhough the client-thread
itself should terminate.
In Indy 9 I created a "TMyListenerThread" that inherited from TIdPeerThread
and overriden AfterRun(), CleanUp() methods so that the "connection" object
(of type TIdTCPConenction) would not be freed or disconnected. (I saved
those connection objects in a list and worked with them)
when I created an object of type TIdTCPServer I did:
TCPListenerServerObject.ThreadClass := TMyListenerThread;
And that solved my problem.
However, Indy10 changed too many thing: TIdContext instead of TIdPeerThread
and the scheduler instead of the threads manager.
So I need a more scalable solution to my problem, such that will not require
re-coding when Indy11 will come out.
Thanks, Offir.
 
 

Re:TCPServer that does not destroy its TIdTCPConnections

I can sympathise with this requirement. Socket components that destroy
per-socket data immediately upin detecting a disconnection make it very
difficult to manage the disconnection thoroughout a complex application.
I would much prefer it if the connection data was queued for, say, two
minutes, after a socket disconnect, (with an internal state set to
'disconnected'), so giving time for the disconnect to flow through an app.
This is almost essential anyway of the per-socket data is pooled, since an
instance must not be re-used for another connection until every thread has
recognised that it can no longer use the connetion & has released any
reference to it. Winsock does eseentially this with its sockets - they are
put into 'TIMED-WAIT', for this very reason - to allow a distributed system
to purge itself.
Rgds,
Martin
 

Re:TCPServer that does not destroy its TIdTCPConnections

"Offir Bakshitz" <nospam>writes:
Quote
Hi all, I'd appretiate an advise:

I need to develop a TCP Server that does not free (nor disconnect) the
socket connection it made with the client, eventhough the client-thread
itself should terminate.

In Indy 9 I created a "TMyListenerThread" that inherited from
TIdPeerThread and overriden AfterRun(), CleanUp() methods so that the
"connection" object (of type TIdTCPConenction) would not be freed or
disconnected. (I saved those connection objects in a list and worked with
them) when I created an object of type TIdTCPServer I did:
TCPListenerServerObject.ThreadClass := TMyListenerThread;
And that solved my problem.

However, Indy10 changed too many thing: TIdContext instead of
TIdPeerThread and the scheduler instead of the threads manager.

So I need a more scalable solution to my problem, such that will not
require re-coding when Indy11 will come out.
Take a look at Synapse.
<www.ararat.cz/synapse/>
--
Best regards
Stig Johansen
 

Re:TCPServer that does not destroy its TIdTCPConnections

"Offir Bakshitz" <nospam>writes
Quote
I need to develop a TCP Server that does not free (nor disconnect)
the socket connection it made with the client, eventhough the client-
thread itself should terminate.
Why would you want that? You can not reassign Connections to different
threads. A given Connection is bound to a given Thread. When the thread
terminates, the Connection is freed. When the Connection disconnects, the
thread is terminated (or re-cached if using thread pooling). There are no
other options. What exactly are you trying to accomplish in the first
place?
Quote
In Indy 9 I created a "TMyListenerThread" that inherited from
TIdPeerThread
and overriden AfterRun(), CleanUp() methods so that the "connection"
object
(of type TIdTCPConenction) would not be freed or disconnected. (I saved
those connection objects in a list and worked with them)
Why do you need to do that? By doing what you are suggesting, you are also
undermining TIdPeerThread's core design. For instance, the Intercept
property will not get cleaned up, and the thread itself will not be managed
properly.
Quote
However, Indy10 changed too many thing: TIdContext instead of
TIdPeerThread and the scheduler instead of the threads manager.
Those were necessary changes. Indy 10 supports more advanced threading
techniques that did not fit in the old model. A re-write was required.
Quote
So I need a more scalable solution to my problem, such that will not
require re-coding when Indy11 will come out.
That is hard to speculate on since Indy 11 hasn't even been started yet.
For all anyone knows, Indy 11 will be re-written again after Indy 10's
successes/failures can be analyzed.
In any case, what you are asking for is not doable in Indy 10. The
Connection is freed in TIdContext's destructor, which you cannot prevent.
So again, I ask you to describe exactly what you are trying to accomplish in
the first place, and why you need to keep Connection objects around after
they have been invalidated. It sounds to me that your design is probably
faulty to begin with, and you do not understand how Indy is meant to be used
in the first place.
Gambit
 

Re:TCPServer that does not destroy its TIdTCPConnections

"Martin James" <XXXX@XXXXX.COM>writes
Quote
I can sympathise with this requirement. Socket components that
destroy per-socket data immediately upin detecting a disconnection
make it very difficult to manage the disconnection thoroughout a
complex application.
Then you need to simplify your complexity. It is not difficult at all to
manage such data, so you are only making your own work harder than it needs
to be.
Gambit
 

Re:TCPServer that does not destroy its TIdTCPConnections

Thank you very much for the reply. I will try to make thing more clear.
This is my scenraio: Our business network is made of hundereds of embedded
devices connected to the Internet. Those devices are the clients, and they
are behind NAT so the server cannot initiate a connection to them. Our
business logic says that If a device is online and there is a message for
that device waiting in the server, the message must arrive at the client
ASAP. However, we cannot have the client devices connect the server and
check for message too often, for two reasons: The Internet connection is
cellular thus we pay per data being transfered, so we wish to avoid
unnecessary data to/from the client. Second problem (less important) is that
if you have hundered of devices openning unnecessary TCP connections all the
time, you get a serious network overload.
We also know that at a given time around 40% of the devices are online.
So our solution was: The clients only connect to the server once every few
minutes. The server then keeps the connection alive by saving the
TIdTCPConnection object in a list and sending a "stay-awake" byte once a
minute to avoid the TCP connection from being deleted due to being idle.
Once a connection was saved, the server allows the thread to terminate
(without terminating the connection). When a message is ready for the
client, the server immediatly uses the already available connection and
sends the message over it [over a worker thread it creaets]. The fact that
the connection is already established also reduces the time it takes for the
message to arrive to the client.
The alive-connections list is maintained in a FIFO manner to a threshold
that we define. Once a connection should leave the list, it is properly
freed. So if a connection is availbale in the list, the message is delivered
immediatly to the client. Otherwise, the server needs to wait unitil that
client creates a new connection to the server.
I would appretiate your remarks on the matter.
 

Re:TCPServer that does not destroy its TIdTCPConnections

"Offir Bakshitz" <nospam>writes
Quote
The clients only connect to the server once every few minutes.
The server then keeps the connection alive by saving the
TIdTCPConnection object in a list and sending a "stay-awake"
byte once a minute to avoid the TCP connection from being
deleted due to being idle. Once a connection was saved, the
server allows the thread to terminate (without terminating the
connection). When a message is ready for the client, the server
immediatly uses the already available connection and sends the
message over it [over a worker thread it creaets]. The fact that
the connection is already established also reduces the time it takes
for the message to arrive to the client.
Indy is not designed to work that way. The thread must be running at all
times while the Connection is alive. If that does not suit your needs, then
using TIdTCPServer is not a suitable choice for your situation in the first
place. Indy 9 servers are thread-based, and as you have already noted, Indy
10 has a different architecture that will make it that much more difficult
to accomplish what you are asking for. You would be better off writing your
own server code manually. Then you can do whatever you want with your
connections. You would not even need to use threads at all if you do not
want to.
Gambit
 

Re:TCPServer that does not destroy its TIdTCPConnections

Quote
Indy is not designed to work that way. The thread must be running at all
times while the Connection is alive. If that does not suit your needs,
then
using TIdTCPServer is not a suitable choice for your situation in the
first
place. Indy 9 servers are thread-based, and as you have already noted,
Indy
10 has a different architecture that will make it that much more difficult
to accomplish what you are asking for. You would be better off writing
your
own server code manually. Then you can do whatever you want with your
connections. You would not even need to use threads at all if you do not
want to.
Would you recommend that I'd use direct Win32 API calls [socket(),
bind(), listen(), select(), send(), recv(), ...]?
When I considered writing my own server, my main worries were:
* Using Windows API calls would make my code harder to upgrade to Delphi
.NET compilation
* I'd lose all the "knowledge" accumulated in the Indy project and will
have to "learn it the hard way" by testing and debugging.