Я пытаюсь отключить неактивные клиенты, подключенные к TIdTCPServer
, независимо от того, отключены ли эти клиенты от их Интернета или в течение неактивного времени.Как отключить неактивные клиенты с помощью TIdTCPServer?
Я попытался установить время ожидания в OnConnect
события, как следующее:
procedure TservForm.TcpServerConnect(AContext: TIdContext);
begin
AContext.Connection.IOHandler.ReadTimeout := 26000;
AContext.Binding.SetSockOpt(Id_SOL_SOCKET, Id_SO_SNDTIMEO, 15000);
end;
Но, кажется, разъединение не запускается после того, как соединение клиента теряется.
Я попытался использовать SetKeepAliveValues()
, но требуется слишком много времени, чтобы отключить неактивный клиент.
Есть ли более полезный способ отключения неактивных клиентов? Итак, если клиент ничего не получил или не отправил, например, через 30 секунд, сервер отключит его?
на выполнение событие
procedure TservForm.TcpServerExecute(AContext: TIdContext);
var
Connection: TConnection;
cmd: String;
Cache, OutboundCmds: TStringList;
MS: TMemoryStream;
I: integer;
S: String;
begin
Connection := AContext as TConnection;
// check for pending outbound commands...
OutboundCmds := nil;
try
Cache := Connection.OutboundCache.Lock;
try
if Cache.Count > 0 then
begin
OutboundCmds := TStringList.Create;
OutboundCmds.Assign(Cache);
Cache.Clear;
end;
finally
Connection.OutboundCache.Unlock;
end;
if OutboundCmds <> nil then
begin
for I := 0 to OutboundCmds.Count - 1 do
begin
AContext.Connection.IOHandler.Writeln(OutboundCmds.Strings[I],
IndyTextEncoding_UTF8);
MS := TMemoryStream(OutboundCmds.Objects[I]);
if MS <> nil then
begin
AContext.Connection.IOHandler.DefStringEncoding := IndyTextEncoding_UTF8;
AContext.Connection.IOHandler.LargeStream := true;
AContext.Connection.IOHandler.Write(MS, 0, true);
end;
end;
end;
finally
if OutboundCmds <> nil then
begin
for I := 0 to OutboundCmds.Count - 1 do
OutboundCmds.Objects[I].Free;
end;
OutboundCmds.Free;
end;
// check for a pending inbound command...
if AContext.Connection.IOHandler.InputBufferIsEmpty then
begin
AContext.Connection.IOHandler.CheckForDataOnSource(100);
AContext.Connection.IOHandler.CheckForDisconnect;
if AContext.Connection.IOHandler.InputBufferIsEmpty then
begin
Exit;
end;
end;
cmd := AContext.Connection.Socket.ReadLn(IndyTextEncoding_UTF8);
...............
...............
Что делает ваш 'OnExecute' обработчик событий выглядит? Тайм-ауты, которые вы используете, зависят от типа ввода-вывода, который вы выполняете. Кроме того, 'SetKeepAliveValues ()' работает для обнаружения мертвых соединений (но не неактивных подключений), хотя не все платформы поддерживают настройку интервалов таймаута keepalive. Другим вариантом будет запуск рабочего потока, который отслеживает соединения и закрывает их сокеты после истечения неактивных тайм-аутов. Вы можете использовать свойство 'TIdContext.Data' для отслеживания последнего времени отправки/получения. –
@RemyLebeau on execute добавлено, на стороне клиента я устанавливаю таймер для отправки команды на сервер каждые 10 секунд –