Delphi 失效的TCP连接
我在Windows服务应用程序中使用Indy10和Delphi XE,其中TIdCmdTCPServer使用TIdTCPClient为客户端提供服务 具有此功能Delphi 失效的TCP连接,delphi,tcp,indy,Delphi,Tcp,Indy,我在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 fina
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。一些印第例外情况不应该在这里被发现,我说得对吗?哪些例外情况?您无法真正确定连接是否“失效”。我要做的是确定连接是否存在超过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;
类型
TClientData=类(ToObject)
ClientName:string;
ClientHost:字符串;
ID:TDateTime;
结束;
类型
TDateTimeO=类(TObject)
公众的
值:TDateTime;
构造函数创建(NewValue:TDateTime);
结束;
常数
MAXCONNECT=(24*60*60);
过程TfrmMain.IdCmdTCPServer1Connect(AContext:TIdContext);
变量
我的客户:TClientData;
开始
AContext.Connection.IOHandler.DefStringEncoding:=IdGlobal.IndytextEncoding8bit;
myClient:=TClientData(AContext.Data);
如果myClient=nil,则
开始
myClient:=TClientData.Create;
AContext.Data:=myClient;
myClient.ClientName:='';
myClient.ClientHost:=AContext.Binding.PeerIP;
myClient.ID:=现在;
结束;
//这实际上发生在我的服务器代码的其他地方,但我已经粘贴了
//它在这里是为了方便
ListBox1.Items.AddObject(
myClient.ClientName+'='+
FormatDateTime('yyyy-mm-dd hh:nn:ss',myClient.ID),
TDateTimeO.Create(myClient.ID));
结束;
程序TfrmMain.Timer1Timer(发送方:TObject);
变量
此时此刻:TDateTime;
i、 j:整数;
名单:TList ;;
名称:字符串;
时间戳:TDateTime;
我的客户:TClientData;
开始
此刻:=现在;
列表:=IdCmdTCPServer1.Contexts.LockList;
尝试
对于i:=ListBox1.Count-1到0
开始
//现在终止实际连接(如果可以找到)
名称:=Trim(TokenStr('=',ListBox1.Items[i],1));
时间戳:=TDateTimeO(ListBox1.Items.Objects[i])值;
if(秒之间(时间戳,此时刻)>MAXCONNECT)
然后
开始
对于j:=List.Count-1到0
开始
如果分配(列表[j]),则
开始
//这是对应的连接吗?
myClient:=TClientData(TIdContext(List[j]).Data);
如果(Name=myClient.ClientName)和
(TDateTimeO(ListBox1.Items.Objects[i]).Value=myClient.ID)然后
开始
TIdContext(列表[j])。连接。断开连接;
打破
结束;
结束;
完下一个j
//有时由于某种原因,连接不在锁定列表中
//仍要删除列表框条目
TDateTimeO(ListBox1.Items.Objects[i]).Free;
列表框1.项目。删除(i);//然后删除列表条目
结束;
完接下来我
最后
IdCmdTCPServer1.Contexts.UnLockList;
结束;
结束;
您无法真正确定连接是否“已断开”。我要做的是确定连接是否存在超过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;
类型
TClientData=类(ToObject)
ClientName:string;
ClientHost:字符串;
ID:TDateTime;
结束;
类型
TDateTimeO=类(TObject)
公众的
值:TDateTime;
构造函数创建(NewValue:TDateTime);
结束;
常数
MAXCONNECT=(24*60*60);
过程TfrmMain.IdCmdTCPServer1Connect(AContext:TIdContext);
变量
我的客户:TClientData;
开始
AContext.Connection.IOHandler.DefStringEncoding:=IdGlobal.IndytextEncoding8bit;
myClient:=TClientData(AContext.Data);
如果myClient=nil,则
开始
myClient:=TClientData.Create;
AContext.Data:=myClient;
myClient.ClientName:='';
myClient.ClientHost:=AContext.Binding.PeerIP;
myClient.ID:=现在;
结束;
//这实际上发生在我的服务器代码的其他地方,但我已经粘贴了
//它在这里是为了方便
ListBox1.Items.AddObject(
myClient.ClientName+'='+
FormatDateTime('yyyy-mm-dd hh:nn:ss',myClient.ID),
TDateTimeO.Create(myClient.ID));
结束;
程序TfrmMain.Timer1Timer(发送方:TObject);
变量
此时此刻:TDateTime;
i、 j:整数;
名单:TList ;;
名称:字符串;
时间戳:TDateTime;
我的客户:TClientData;
开始
此刻:=现在;
列表:=IdCmdTCPServer1.Contexts.LockList;
尝试
对于i:=ListBox1.Count-1到0
开始
//现在终止实际连接(如果可以找到)
名称:=Trim(TokenStr('=',ListBox1.Items[i],1));
时间戳:=TDateTimeO(ListBox1.Items.Objects[i])值;
if(秒之间(时间戳,此时刻)>MAXCONNECT)
然后
开始
对于j:=List.Count-1到0
开始
如果分配(列表[j]),则
开始
//这是对应的连接吗?
myClient:=TClientData(TIdContext(List[j]).Data);
如果(Name=myClient.ClientName)和
(TDateTimeO(ListBox1.Items.Objects[i]).Value=myClient.ID)然后