我在Windows服务应用程序中使用Indy10和Delphi XE,而TIdCmdTCPServer使用TIdTCPClient为客户端提供服务。
具有此功能
function ConnectionCount: Integer;
begin
if IdCmdTCPServer.Contexts = nil then
Exit(0);
with IdCmdTCPServer.Contexts do
try
Result := LockList.Count
finally
UnlockList
end;
end;
我得到了从客户端到服务器的连接数。有时,即使关闭了所有客户端,此计数也不会降至零。我想这些连接已经死了。在一个有5个客户端的网站上,经过几个星期的操作,我发现连接计数为35。
有没有办法检测到连接已死并释放它?
我怀疑如果客户端冻结或被杀死,连接可能会死掉,但我不知道这种情况是否存在。
编辑:这是我的TIdCmdTCPServer处理程序之一的代码:
procedure TDSA_Service.ModeHandler(ASender: TIdCommand);
var
R: TToolReply;
begin
FBMutex.Enter;
try
try
R := SystemServer.Mode(GetIntParam(0, 'SystemNo', ASender));
try
Reply(ASender, R)
finally
R.Free
end
except
HandleException;
Abort
end
finally
FBMutex.Leave
end
end;
HandleException是madEx,除了发送错误报告。我是不是应该在这里捕获一些印地例外?哪些例外?
答案 0 :(得分:2)
您不能真正确定连接是否“死”。我要做的是确定连接是否存在超过24小时,如果存在则将其删除。 我不在乎雷米提出的“为什么连接会徘徊”的问题。我的用户也不介意他们第二天早上来只是发现他们的客户不再响应。我希望这段代码能回答的问题多于提出的问题。
type
TClientData = class(TObject)
ClientName: string;
ClientHost: string;
ID: TDateTime;
end;
type
TDateTimeO = Class(TObject)
public
Value: TDateTime;
constructor Create(NewValue: TDateTime);
end;
const
MAXCONNECT = (24 * 60 * 60);
procedure TfrmMain.IdCmdTCPServer1Connect(AContext: TIdContext);
var
myClient: TClientData;
begin
AContext.Connection.IOHandler.DefStringEncoding := IdGlobal.IndyTextEncoding_8Bit;
myClient := TClientData(AContext.Data);
if myClient = nil then
begin
myClient := TClientData.Create;
AContext.Data := myClient;
myClient.ClientName := '<Unknown>';
myClient.ClientHost := AContext.Binding.PeerIP;
myClient.ID := Now;
end;
// this actually happens elsewhere in my server code, but I've pasted
// it here for convenience
ListBox1.Items.AddObject(
myClient.ClientName + '=' +
FormatDateTime('yyyy-mm-dd hh:nn:ss', myClient.ID),
TDateTimeO.Create(myClient.ID));
end;
procedure TfrmMain.Timer1Timer(Sender: TObject);
var
ThisMoment: TDateTime;
i, j: Integer;
List: TList;
Name: String;
TimeStamp: TDateTime;
MyClient: TClientData;
begin
ThisMoment := Now;
List := IdCmdTCPServer1.Contexts.LockList;
try
for i := ListBox1.Count - 1 downto 0 do
begin
// now terminate the actual connection (if it can be found)
Name := Trim(TokenStr('=', ListBox1.Items[i], 1));
TimeStamp := TDateTimeO(ListBox1.Items.Objects[i]).Value;
if (SecondsBetween(TimeStamp, ThisMoment) > MAXCONNECT)
then
begin
for j := List.Count - 1 downto 0 do
begin
if Assigned(List[j]) then
begin
// is this the corresponding connection?
myClient := TClientData(TIdContext(List[j]).Data);
if (Name = myClient.ClientName) and
(TDateTimeO(ListBox1.Items.Objects[i]).Value = myClient.ID) then
begin
TIdContext(List[j]).Connection.Disconnect;
BREAK;
end;
end;
end; // next j
// sometimes the connection isn't in the locklist for some reason
// delete the listbox entry anyway
TDateTimeO(ListBox1.Items.Objects[i]).Free;
ListBox1.Items.Delete(i); // and delete the list entry
end;
end; // next i
finally
IdCmdTCPServer1.Contexts.UnLockList;
end;
end;