TCP Keep Alive на idHttpServer (сервер) и wininet (клиент) - PullRequest
5 голосов
/ 04 мая 2011

У меня есть приложение веб-сервера, разработанное с использованием idHttpServer. Когда клиент подключается, сделать мой веб-сервер и, по какой-то неизвестной причине, получил отключение (не изящное отключение), мой веб-сервер не получает уведомления. Я знаю, что это нормальное поведение, но мне нужно знать, когда клиент умрет.

Есть несколько способов сделать это. Я знаю 2 хороших способа:

1 - Реализация механизма сердцебиения. Клиентский сокет уведомляет сервер о том, что он все еще жив (требуется некоторая работа и некоторый код для его работы)

2 - TCP Keep Alive . Этот способ мне нравится больше всего, потому что он требует не слишком много кода и работы. Но у меня есть несколько вопросов по этому поводу.

  • Возможно ли это использовать с idHttpServer (для сервера) и функции wininet (для клиента)?
  • Это действительно работает, как ожидалось? Я имею в виду, сервер не получает уведомления, когда клиент все время умирает?
  • У кого-нибудь есть пример установки этого на wininet? (Я полагаю, это должно быть установлено на стороне клиента, верно?)
  • Есть ли лучший способ уведомить сервер о том, что клиент мертв (с помощью indy и wininet, конечно)

EDIT

Я использую Delphi 2010 и последний исходный код Indy10 из их svn.

1 Ответ

4 голосов
/ 05 мая 2011

Если вы используете актуальную версию Indy 10, вы можете использовать метод TIdSocketHandle.SetKeepAliveValues():

procedure SetKeepAliveValues(const AEnabled: Boolean; const ATimeMS, AInterval: Integer);

Например:

procedure TForm1.IdHTTPServer1Connect(AContext: TIdContext);
begin
  // send a keep-alive every 1 second after
  // 5 seconds of inactivity has been detected
  AContext.Binding.SetKeepAliveValues(True, 5000, 1000);
end;

Обратите внимание, чтопараметры ATimeMS и AInterval поддерживаются только в Windows 2000 и более поздних версиях.

В противном случае используйте метод TIdSocketHandle.SetSockOpt() напрямую, чтобы вручную включить параметр TCP / IP SO_KEEPALIVE:

procedure TIdSocketHandle.SetSockOpt(ALevel: TIdSocketOptionLevel; AOptName: TIdSocketOption; AOptVal: Integer);

Например:

procedure TForm1.IdHTTPServer1Connect(AContext: TIdContext);
begin
  AContext.Binding.SetSockOpt(Id_SOL_SOCKET, Id_SO_KEEPALIVE, 1);
end;
...