2

我有三个问题:

  1. 是否可以通过多个连接来破坏 IdTCPServer?我尝试测试我的应用程序,当我有多个连接时 - 它工作得非常好(甚至几天),但有时连接数量增加时,应用程序会违反访问权限。我编写的应用程序模拟了 50 个客户端不断发送数据(只有 sleep(200))。在这种情况下,IdTCPServer 会给出异常吗?我的应用程序通过 onExecute 事件从客户端获取信息,并使用 TidNotify 和 TIdSync 类修改数据库表。我相信它可以保护交叉连接线程?向客户端发送信息是由 TTimer 完成的(只是现在,我将其更改为其他线程)。我是否在这种情况下使用特殊保护或类似的东西就足够了:

    type
      PClient = ^TClient;
      TClient = record
        Activity_time:TDateTime;
        AContext: TIdContext;
      end;
    ...
    list := server.Contexts.LockList;
    try
     for i := 0 to list.Count - 1 do
      with TIdContext(list[i]) do
      begin
    
        if SecondsBetween(now(), PClient(data)^.activity_time) > 6 then
        begin
          Connection.IOHandler.Close;
          Continue;
        end;
        try
          Connection.IOHandler.writeln('E:');
        Except
          Connection.IOHandler.Close;
        end;
      end;
    finally
      server.Contexts.UnlockList;
    end;
    

2.当服务器繁忙时拒绝连接是一种简单的方法(我认为我的数据库并不复杂(100行,一个连接只修改一行)但也许这是一种保持服务器稳定性的方法?

3.我知道这个问题重复了很多次,但我没有找到满意的答案:如何保护应用程序以避免消息异常:“连接正常关闭”和“对等连接重置”?

谢谢你的所有建议

4

1 回答 1

3

是否可以通过多个连接来破坏 IdTCPServer?

你问错了问题,因为你实际上并没有破坏TIdTCPServer自己,你只是从外部线程关闭空闲连接。可以(并且应该)在OnExecute事件内部处理这种逻辑,而不是在最安全的地方访问连接,例如:

type
  PClient = ^TClient;
  TClient = record
    Activity_time: TDateTime;
    Heartbeat_time: TDateTime;
    AContext: TIdContext;
  end;

procedure TForm1.serverConnect(AContext: TIdContext);
var
  Client: PClient;
begin
  New(Client);
  Client^.Activity_time := Now();
  Client^.Heartbeat_time := Client^.Activity_time;
  AContext.Data := TObject(Client);
end;

procedure TForm1.serverDisconnect(AContext: TIdContext);
var
  Client: PClient;
begin
  Client := PClient(AContext.Data);
  AContext.Data := nil;
  if Client <> nil then Dispose(Client);
end;

procedure TForm1.serverExecute(AContext: TIdContext);
var
  Client: PClient;
  dtNow: TDateTime;
begin
  Client := PClient(AContext.Data);
  dtNow := Now();

  if SecondsBetween(dtNow, Client^.Activity_time) > 6 then
  begin
    AContext.Connection.Disconnect;
    Exit;
  end;

  if SecondsBetween(dtNow, Client^.Heartbeat_time) > 2 then
  begin
    AContext.Connection.IOHandler.WriteLn('E:');
    Client^.Heartbeat_time := dtNow;
  end;

  if AContext.Connection.IOHandler.InputBufferIsEmpty then
  begin
    if not AContext.Connection.IOHandler.CheckForDataOnSource(100) then
      Exit;
  end;

  // process incoming data as needed ...

  Client^.Activity_time := Now();
end;

当服务器繁忙时拒绝连接是一种简单的方法(我认为我的数据库并不复杂(100行,一个连接只修改了一行)但也许这是一种保持服务器稳定性的方法?

当前架构不允许拒绝接受连接。您可以让服务器正常接受连接,然后在需要时关闭接受的连接。您可以在这种情况下这样做OnConnect,或者您可以将服务器的MaxConnection属性设置为一个非零的低数字,以允许服务器为您自动断开新连接,而不会浪费资源TIdContext为它们创建新对象和线程。

另一种选择是StopListening()在服务器繁忙时调用服务器的方法,这样新的连接就无法再到达服务器,然后在StartListening()准备好再次接受新客户端时调用服务器的方法。已经连接的现有客户端不应该受到影响,尽管我自己还没有真正尝试过。

我知道这个问题重复了很多次,但我没有找到令人满意的答案:如何保护应用程序以避免消息异常:“连接正常关闭”和“对等连接重置”?

你不应该避开它们。让它们发生,它们是正常的错误。如果它们发生在服务器事件中,只需让服务器为您正常处理它们。这就是TIdTCServer设计使用的方式。如果它们发生在服务器事件之外,例如在您的计时器中,那么只需将套接字操作包装在一个try/except块中并继续前进。

于 2013-01-02T18:17:53.623 回答