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:= '1';
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
1". 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