I faced strange issue when connected clients seem not to be removed from 
server's list on disconnect.
I wrote simple demo project to test this, it'll be later. In short words, 
client objects seem to never be deleted from FClientList. I've set breakpoint 
on the line "FClientList.Remove(AComponent)" in 
TCustomWSocketServer.Notification - it's never reached. So client is destroyed, 
but server still thinks he has it, and when destroying the server or calling 
DisconnectAll the exception "Invalid pointer operation" is raised.

Here's the demo:

== start ==

unit Servers;

interface

uses
  Windows, Messages, SysUtils, Classes, StrUtils, DateUtils,
  OverbyteIcsWSocket, OverbyteIcsWinsock, OverbyteIcsLogger,
  OverbyteIcsWSocketS, OverbyteIcsWndControl;

procedure ServersInit;
procedure ServersFree;

implementation

type
  TSrvClient = class(TWSocketClient)
  protected
    FList: TList;
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
  end;

  TServer = class(TCustomWSocketServer)
  protected
    procedure TriggerClientConnect(Client: TWSocketClient; Error: Word); 
override;
    procedure TriggerClientDisconnect(Client: TWSocketClient; Error: Word); 
override;
  public
    constructor Create(AOwner: TComponent); override;
  end;

var Server: TServer;

procedure ServersInit;
begin
  Server := TServer.Create(nil);{}
  Server.ClientClass := TSrvClient;
  Server.Listen;
end;

procedure ServersFree;
begin
  FreeAndNil(Server);
end;

constructor TSrvClient.Create(AOwner: TComponent);
begin
  inherited;
  CreateCounter;
  ComponentOptions := [wsoNoReceiveLoop];
  FList := TList.Create;
end;

destructor TSrvClient.Destroy;
begin
  FreeAndNil(FList); // *** set breakpoint here to ensure client is destroyed 
***
end;

constructor TServer.Create(AOwner: TComponent);
begin
  inherited;
  Proto           := 'tcp';
  Addr            := '0.0.0.0';  // Use any interface
  Port            := '10000';
  ClientClass     := TSrvClient; // Use our component
  Banner          := '';
  BannerTooBusy   := '';
end;

procedure TServer.TriggerClientConnect(Client: TWSocketClient; Error: Word);
begin
  inherited;
  Client.SendLine('Connect OK, closing...');
  Client.CloseDelayed;
end;

procedure TServer.TriggerClientDisconnect(Client: TWSocketClient; Error: Word);
begin
  inherited;
end;

end.

== end ==

How to test.

Save this as unit Servers, start new VCL app, use the unit, drop 2 buttons and 
create handlers:
procedure TForm1.Button1Click(Sender: TObject);
begin
  ServersInit;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  ServersFree;
end;

Run the app, push the 1st button. Launch cmd.exe and type "telnet localhost 
10000". You'll receive a message and connection will be closed. But breakpoint 
on the line "FClientList.Remove(AComponent)" in 
TCustomWSocketServer.Notification isn't reached. Now push the 2nd button. 
Exception.

I believe in TCustomWSocketServer.WMClientClosed RemoveComponent should be 
called before Client.Free. I tried it and everything's OK.

-- 
Anton
--
To unsubscribe or change your settings for TWSocket mailing list
please goto http://lists.elists.org/cgi-bin/mailman/listinfo/twsocket
Visit our website at http://www.overbyte.be

Reply via email to