【问题标题】:Robust unidirectional messages with Indy使用 Indy 实现强大的单向消息
【发布时间】:2009-06-12 13:05:44
【问题描述】:

我有一个客户端应用程序应该向可选的服务器应用程序发送通知消息。客户端不应受到服务器应用程序是否存在的影响。它应该尝试连接到服务器应用程序并发送通知消息,如果出现错误,它应该默默地忽略所有错误并继续工作。

我正在使用 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;

【问题讨论】:

    标签: delphi delphi-2009 client-server indy


    【解决方案1】:

    你真的从你的程序收到错误信息吗?调试时调试器检测到异常并中断您的程序是很常见的,有些人将调试器的消息与来自他们自己程序的消息混淆。你确定这里不是这样吗? I've written about this situation before.以下是避免它的方法摘要:

    • 使用“高级断点”禁用调试器对代码区域的异常拦截行为。
    • 将调试器配置为忽略某些类别的异常。 (这在 Indy 中尤为常见,因为它往往会引发许多异常。)
    • 将调试器设置为从不因异常而中断程序。
    • 完全禁用集成调试。

    如果消息确实来自您的程序而不是调试器,则返回并使用调试器找出消息的来源。当消息出现时,暂停程序并查看调用堆栈窗口以找到显示消息的代码区域,因为它显然不在您显示的代码中。您显示的代码完全抑制(而不是处理)所有异常,即使是与 Indy 无关的异常,例如 EAccessViolationEOutOfMemory

    【讨论】:

    • 您好,Rob,感谢您的回答。不在调试器中运行应用程序时会出现该消息。我通过在每个通知上连接和断开连接来修复它(不会经常发生)。它现在看起来很健壮。
    【解决方案2】:

    对于简单的 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 中。

    【讨论】:

      【解决方案3】:

      如果可能,请考虑使用 UDP。它是“无连接的”,因此发送者只会发送消息,而接收应用程序将在侦听端口时接收它。但是,除非服务器发送某种确认,否则发件人不会得到任何有关交付的确认。

      【讨论】:

      • 我想使用现有的通信协议,因此想坚持使用 TCP。无论如何,谢谢。
      • Indy 一直以来都有 UDP。还是您的意思是“现有的通信协议”,您想适应您的应用程序已经在做的事情?
      【解决方案4】:

      Harriv 响应正常,您正在描述 UDP 连接的行为。我正在使用类似的情况。

      【讨论】:

        【解决方案5】:

        您没有说您使用的是 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 的过程很容易。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-06-01
          • 1970-01-01
          • 2013-05-01
          • 1970-01-01
          • 1970-01-01
          • 2011-05-01
          • 2017-03-22
          • 2014-08-28
          相关资源
          最近更新 更多