3

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

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

5 回答 5

3

你真的从你的程序中得到错误信息吗?调试时调试器检测到异常并中断您的程序是很常见的,有些人将调试器的消息与来自他们自己程序的消息混淆。你确定这里不是这样吗?我以前写过这种情况。以下是避免它的方法的摘要:

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

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

于 2009-06-12T15:18:29.077 回答
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 中。

于 2009-06-17T21:20:25.743 回答
0

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

于 2009-06-12T21:44:43.860 回答
0

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

于 2009-06-12T17:59:33.697 回答
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 的过程很容易。

于 2009-08-12T12:47:22.347 回答