无效的TCP连接

时间:2018-08-22 13:12:57

标签: 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
  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,除了发送错误报告。我是不是应该在这里捕获一些印地例外?哪些例外?

1 个答案:

答案 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;