使用Indy的强大单向消息

时间:2009-06-12 13:05:45

标签: delphi delphi-2009 client-server indy

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

我正在使用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 个答案:

答案 0 :(得分:3)

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

  • 使用“高级断点”来禁用调试器对代码区域的异常拦截行为。
  • 配置调试器以忽略某些类别的异常。 (这与Indy特别常见,因为它往往会抛出许多例外。)
  • 将调试器设置为永不中断异常程序。
  • 完全禁用集成调试。

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

答案 1 :(得分: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中。

答案 2 :(得分:0)

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

答案 3 :(得分:0)

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

答案 4 :(得分:0)

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