Indy 的强大单向消息

发布于 2024-07-23 17:02:19 字数 738 浏览 6 评论 0原文

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

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

I have a client application that should send notify messages to an optional server application. The client should not be influenced by whether the server appliction exists or not. It should try to connect to the server application and send the notify message and in case of errors it should just silently ignore all errors and continue work.

I'm using Indy for the TCP communication but all attempts to avoid error messages showing up (i.e. when ther server application closes while connected to the client) failed.

Is there a way to really make this robust?

Current code looks like this:

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;

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

断肠人 2024-07-30 17:02:19

您真的从您的程序中收到错误消息吗? 调试时,调试器会检测到异常并中断程序,这是很常见的,有些人会将调试器的消息与来自自己程序的消息混淆。 您确定这里不是这种情况吗? 我之前写过有关这种情况的文章。以下是解决此问题的方法的摘要避免它:

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

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

Do you really get error messages from your program? It's common that when debugging that the debugger detects exceptions and interrupts your program, and some people confuse the debugger's message for a message from their own program. Are you sure that's not the case here? I've written about this situation before. Here's the summary of ways to avoid it:

  • Use "advanced breakpoints" to disable the debugger's exception-interception behavior for a region of code.
  • Configure the debugger to ignore certain classes of exceptions. (This is especially common to do with Indy since it tends to throw many exceptions.)
  • Set the debugger to never interrupt the program on exceptions.
  • Disable integrated debugging altogether.

If the message really is coming from your program and not the debugger, then go back and use the debugger to figure out where the message is coming from. When the message appears, pause the program and look at the call-stack window to find the area of your code that's displaying the message, since it clearly isn't in the code you've shown. The code you've shown is thoroughly suppressing (not handling) all exceptions, even the ones that aren't related to Indy, such as EAccessViolation and EOutOfMemory.

夏日落 2024-07-30 17:02:19

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

For simple TCP communications task I've used Synapse package, it's not as bloated as Indy and feels "cleaner" to use.

From my recent code:

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;

Wrap that inside TThread if you want to avoid blocking your current thread.

荒岛晴空 2024-07-30 17:02:19

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

If possible, consider using UDP. It's "connectionless", so sender will just send the message and receiving application will receive it if it is listening to the port. However the sender doesn't get any confirmation about the delivery unless the server sends some kind of acknowledgement.

风吹短裙飘 2024-07-30 17:02:19

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

Harriv response is OK, you are describing the behaviour of an UDP connection. I'm using in a similar situation.

陌若浮生 2024-07-30 17:02:19

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

You don't say whether you're using Indy 9 or 10. I use 9, myself, so the below assumes this.

Why not just this?:

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;

It's easy enough to turn this into a procedure that uses a pre-existing TIdTcpClient.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文