Newsgroups : Borland : borland.public.delphi.internet.winsock : 2007 Mar : Re: Creating TCP server with blocking Indy components?

www.cryer.info
Managed Newsgroup Archive

Re: Creating TCP server with blocking Indy components?

Subject:Re: Creating TCP server with blocking Indy components?
Posted by:"Bo Berglund" (bo.berglu..@telia.com)
Date:Sat, 24 Mar 2007 09:11:17

On Fri, 23 Mar 2007 18:03:53 -0800, "Remy Lebeau \(TeamB\)"
<no.spam@no.spam.com> wrote:

>
>"Bo Berglund" <bo.berglund@telia.com> wrote in message
>news:nao8031flnt3sv31uk53al06tlu17hqu0r@4ax.com...
>
>> Just downloaded the docs. My-oh-my, it is a 3187 page
>> PDF file and no really useful indexing either....
>
>The Indy-In-Depth eBook is not the documentation I was referring to.

I am not either. I went to the docs link
http://www.indyproject.org/Sockets/Docs/index.aspx
and it contains a hard-to-read PDF with all those pages...

>
>> OK, so the event fires by itself also with no data being received???
>> Strange.
>
>The most common thing done when writing a blocking threaded server is
>to write a 'while not Terminated' loop in the thread.  So TIdTCPServer
>does that for you internally, allowing you to focus your code on just
>what happened for each iteration of the loop.

OK, so I stay in the loop eternally then. Can I do like so:

procedure TServerFrmMain.ServerExecute(AThread: TIdPeerThread);
var
  sRecData: string;
begin
  while not AThread.Terminated and AThread.Connection.Connected then
  begin
    sRecData := AThread.Connection.ReadLn('</msg>', 2000);
    if sRecData = '' then Continue;
    do some stuff with RecData like stuffing it into a buffer (how)...
  end;
end;

Now I come back to my problem of handling the "comands" the server
needs to *send* to the "client" (it is really a screwy system this
tool maker has designed...):
The connection to the client is maintained in a thread of its own and
my main application needs to send commands to the client at irregular
intervals controlled by things that happen in the main part of the
application. So how can I get hold of that specific connection there
and send the string out?

Should I capture the AThread object in a variable in the main program
when the connection is done (remember, only one allowed connection)
and later use its methods via the variable?
What will happen with the threading model then? Will my main
application again be locked up? Or can I do it the way I outline
below?

They have designed the system so that any command sent to the client
will result in two things:
1) An "immediate" same socket reply from the client (acts more like a
server here...) with an acknowledge or some easily accessible data.

2) At a later time a message on the other socket from the client where
the result of a lengthy operation is supplied intermixed with other
status messages. None of these need to be responded to.

I guess that the type 2 messages will be like normal server activity
and I can handle that by reading the data and not replying at all. So
I don't need to stay in any loop, just handle it in the OnExecute
event?

The concern now is the type 1 handling, i.e. how to send a message
from the main application using the thread that is in an eternal loop.

Would this work:

Private variables in the form level:
  FClientConnected,
  FMessageToSend: boolean; {global flags}
  FMessageText: string; {global message container string}

procedure TServerFrmMain.ServerConnect(AThread: TIdPeerThread);
begin
  FClientConnected := true;
  while not AThread.Terminated and AThread.Connection.Connected then
  begin
    if FMessageToSend then
    begin
      AThread.Connection.Write(FMessageText);
      FMessageToSend := false; {reset semaphore}
    end;
  end;
  FClientConnected := false;
end;

Then in the main application:

procedure TServerFrmMain.SendCommand(Command: string): boolean;
var
begin
  Result := false;
  if not FClientConnected then exit;
  try
    while FMessageToSend do {wait until previous message is done}
    begin
      Sleep(1);
      Application.ProcessMessages;
    end;
    FMessageText := Command;
    FMessageToSend := true;
    Result := true;
  except
  end;
end;

Then any message that arrives from the connected client on any of the
two channels have to be put into some list container that is examined
in the main application somehow in order not to tie up the socket
thread with that.
How can I make sure that I am not accessing this list in the main
application when the thread is also doing so? Using semaphores like
above?

>> It contains a lot of extraneous files as well, which the 9.0.18 zip
>> does not.
>
>Such as?

Such as 80 files in a sub dir "Boxter" and below that.
And 1 file in a subdir SyncObjs

These directories are not present at all in the 9.0.18 zipfile.

>> Are there real improvements to the dev snapshot?
>
>Yes.  Many of the units have received updates since 9.0.18 was
>released in late 2004.

OK, so I need 9.0.50 then....

Thanks,

Bo

Replies:

none

In response to:

www.cryer.info
Managed Newsgroup Archive