Надежные однонаправленные сообщения с Indy - PullRequest
3 голосов
/ 12 июня 2009

У меня есть клиентское приложение, которое должно отправлять уведомления на дополнительное серверное приложение. Клиент не должен зависеть от того, существует приложение сервера или нет. Он должен попытаться подключиться к серверу приложения и отправить сообщение уведомления, а в случае ошибок он должен просто молча игнорировать все ошибки и продолжить работу.

Я использую Indy для связи по протоколу TCP, но все попытки избежать появления сообщений об ошибках (т. Е. Когда приложение сервера закрывается при подключении к клиенту) завершились неудачей.

Есть ли способ действительно сделать это надежным?

Текущий код выглядит так:

if (not Client.Connected) then
  begin
  Client.Host := ServerName;
  Client.Port := ServerPort;
  Client.ConnectTimeout := ConnectTimeout;
  try
    Client.Connect;
  except
    Exit;
  end;
  end
try
  Client.IOHandler.WriteLn ('NOTIFYCHANGE "' + Param + '"');
  Client.IOHandler.WriteBufferFlush;
except
  try
    Client.Disconnect;
  except
    { ignore errors while disconnecting }
  end;
  try
    Client.Connect;
  except
    { ignore errors while connecting }
  end;
end;

Ответы [ 5 ]

3 голосов
/ 12 июня 2009

Вы действительно получаете сообщения об ошибках от вашей программы? Обычно при отладке отладчик обнаруживает исключения и прерывает вашу программу, а некоторые люди путают сообщение отладчика с сообщением из собственной программы. Вы уверены, что это не тот случай? Я уже писал об этой ситуации. Вот краткое изложение способов избежать этого:

  • Используйте "расширенные точки останова", чтобы отключить поведение перехвата исключения отладчика для области кода.
  • Настройте отладчик на игнорирование определенных классов исключений. (Это особенно распространено в Indy, поскольку он вызывает много исключений.)
  • Настройте отладчик так, чтобы он никогда не прерывал выполнение программы при исключениях.
  • Отключить встроенную отладку в целом.

Если сообщение действительно исходит от вашей программы, а не отладчика, вернитесь назад и используйте отладчик, чтобы выяснить, откуда пришло сообщение. Когда появится сообщение, остановите программу и посмотрите в окно стека вызовов, чтобы найти область кода, в которой отображается сообщение, поскольку его явно нет в коде, который вы показали. Код, который вы показали, полностью подавляет (не обрабатывает) все исключения, даже те, которые не связаны с Indy, такие как EAccessViolation и EOutOfMemory.

2 голосов
/ 18 июня 2009

Для простой задачи связи TCP я использовал пакет Synapse , он не такой раздутый, как Indy, и чувствует себя «чище» в использовании.

Из моего недавнего кода:

procedure SendMessage(m: string);
var
  sock : TTCPBlockSocket;
  response : string;
begin
  Sock := TTCPBlockSocket.Create;
  try
    Sock.SetTimeout(200);
    Sock.Connect(PrinterServerAddr, IntToStr(PrinterServerPort));

    Sock.SendString(m);
    response := Sock.RecvString(1000);
  finally
    Sock.Free;
  end;
end;

..
try
  SendMessage(NewMessage);
except
 //..handle exception..
end;

Оберните это внутри TThread, если вы хотите избежать блокировки текущего потока.

0 голосов
/ 12 августа 2009

Вы не говорите, используете ли вы Indy 9 или 10. Я сам использую 9, поэтому нижеприведенное подразумевает это.

Почему бы не это?

procedure Send(Target: String; Port: Integer; S: String);
var
  C: TIdTcpClient;
begin
  C := TIdTcpClient.Create(nil);
  try
    try
      C.Host := Target;
      C.Port := Port;
      C.Connect;
      try
        C.Write(S);
      finally
        C.Disconnect;
      end;
    except
      // Ignore Indy exceptions
      on EIdException do;
    end;
  finally
    C.Free;
  end;
end;

Достаточно просто превратить это в процедуру, которая использует уже существующий TIdTcpClient.

0 голосов
/ 13 июня 2009

Ответ Харрива в порядке, вы описываете поведение UDP-соединения. Я использую в аналогичной ситуации.

0 голосов
/ 12 июня 2009

Если возможно, рассмотрите возможность использования UDP. Оно «без установления соединения», поэтому отправитель просто отправит сообщение, а получающее приложение получит его, если прослушивает порт. Однако отправитель не получает никакого подтверждения о доставке, если сервер не отправляет какое-либо подтверждение.

...