Delphi: 为 TIdHttpServer 设置连接超时

Delphi: Setting connection timeout for TIdHttpServer

使用 TIdHTTPServer(Indy 10.6),我想为关闭缓慢或不活动的客户端(客户端是普通浏览器)设置连接超时,并在 60 秒不活动后关闭所有僵尸连接。我在 TIdContext.Connection 中找到了 Socket.ReadTimeout。这是正确的方法吗? TIdHTTPServer 已经执行此操作(似乎有无限超时)?

WebServer := TIdHTTPServer.Create(nil);
WebServer.SessionState := false;
WebServer.KeepAlive    := false;
WebServer.OnCommandGet := CustomOnCommandGet;

procedure CustomOnCommandGet(AContext: TIdContext; ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo;
begin
    AContext.Connection.Socket.ReadTimeout := 60000;
    AResponseInfo.ContentStream := TFileStream.Create('C:/file.zip', fmOpenRead or fmShareCompat);
end;

你的方向是正确的,ReadTimeout 属性 可以用来断开 slow/dead 没有及时发送请求的客户端。但是,您在错误的地方设置了 ReadTimeout

OnCommand... 事件被触发时,TIdHTTPServer 已经完整读取了客户端的请求,因此您的新设置将在 下一个 在同一连接上请求,如果有的话。因此,您应该在 OnConnect 事件中设置 ReadTimeout 值:

WebServer.OnConnect := CustomOnConnect;

procedure CustomOnConnect(AContext: TIdContext);
begin
  AContext.Connection.Socket.ReadTimeout := 60000;
end;

请记住,HTTP 是无状态的。多个 HTTP 请求可以在同一连接上发送 仅当 使用 HTTP keep-alives 时,这是可选的。如果没有keep-alives,服务器会在发送响应后关闭连接。客户端必须重新连接才能发送新请求。

您正在将服务器的 KeepAlive 属性 设置为 false,因此不会有任何 keep-alives 受到尊重,每个请求之后都会断开连接。因此,您需要在 OnConnect 事件中设置 ReadTimeout 以将其应用于在每个连接上发送的唯一请求。但是,如果您启用 KeepAlive,并且客户端请求保持活动状态,则 ReadTimeout 将应用于客户端在同一连接上发送的每个请求,尤其是第一个请求。