2

I have small problem (I wish it's small) with disconnecting server - I mean - only in the moment when I want to disconnect it from server application (server.active=false). Here is my simple code:

    type
      PClient = ^TClient;
    type
      TClient = record
        Name: string;
        AContext: TIdContext;
    end;


     clients: TThreadList;
     SERVER: TIdTCPServer; 

    procedure TX.SERVERConnect(AContext: TIdContext);
    var
      NewClient: PClient;
      s:string;
    begin
        s := AContext.Connection.socket.ReadLn();
        GetMem(NewClient, SizeOf(TClient));
        NewClient.name:=s;
        NewClient.AContext := AContext;
        AContext.data := TObject(NewClient);
        try
          clients.LockList.Add(NewClient);
        finally
          clients.UnlockList;
        end;
        AContext.Connection.socket.writeln('E:');//answer to client - "all right"
    End;


    procedure TX.SERVERDisconnect(AContext: TIdContext);
    var
      AClient: PClient;
    begin
      AClient := PClient(AContext.data);
      try
        clients.LockList.Remove(AClient);
      finally
        clients.UnlockList;
      end;
      FreeMem(AClient);
      AContext.data := nil;
    end;

It have to works only for sending data to clients therefore I read only one data line in onconnect procedure - it contains login name.

Procedure for sending data in my code looks like (is it good?):

    var
    procedure TX.send(what: string; where: string);
      i, ile: integer;
      s: string;
      Aclient: PClient;
      list: tlist;
    begin
      list:= SERVER.Contexts.LockList;
      try
        for i := 0 to list.Count - 1 do
          with TIdContext(list[i]) do
          begin
            AClient := PClient(data);
            if where = ActClient^.name then
              Connection.IOHandler.writeln(what);
          end;
      finally
        SERVER.Contexts.UnlockList;
      end;
    end;

It looks it works good - I mean. But when I want to disable server by SERVER.active:=false application freezes? I tried to free clients etc. but it dosen't work in my bad code.

Could Somebody help me and give me advice how to stop server for this code?

Artik

Artik
  • 803
  • 14
  • 36
  • What does the server do in the OnExecute loop? Maybe a deadlock occurs there, or exception handling interferes with Indy. – mjn Dec 13 '12 at 10:24
  • Server doesn't do nothing in the OnExecute - After given login (it is reading one "line" in OnConnection) Client doesn't sending data - only server send to Client. – Artik Dec 13 '12 at 13:49
  • You still have to provide an `OnExecute` event handler, even if it just calls Sleep(). Otherwise TIdTCPServer can enter a tight unyielding loop that eats up all available CPU cycles. Depending on where Send() is being called from, you could give each client its own outbound queue that Send() puts entries into, and then have OnExecute handle flushing the queue to the connection when needed. – Remy Lebeau Dec 14 '12 at 03:51
  • Also, without an OnExecute event handler that accesses the socket periodically, raising an exception on disconnect, the thread that manages the socket may not ever terminate itself, which would account for your deadlock since TIdTCPServer waits for threads to terminate. – Remy Lebeau Dec 14 '12 at 03:57
  • 1
    Lastly, get rid of your `clients` list completely. You are not using it for anything, you are not using it correctly anyway, and it is redundant since it is just duplicating what the `TIdTCPServer.Contexts` property already does. – Remy Lebeau Dec 14 '12 at 04:00
  • I apologize. I was out of the possibility for improving my code. Remy, could You be so polite to show me simple code example of using TIdTCPServer.Contexts and finally disconnect server by using server.active:=false without bad freezing application? I tried convert my application for using Your suggestion but I've got the same result. My application doesn't respond after switching of the server by using server.active:=false; – Artik Dec 20 '12 at 21:08

0 Answers0