3

オプションのサーバーアプリケーションに通知メッセージを送信する必要があるクライアントアプリケーションがあります。クライアントは、サーバーアプリケーションが存在するかどうかに影響されないようにする必要があります。サーバーアプリケーションへの接続を試みて通知メッセージを送信し、エラーが発生した場合は、すべてのエラーを黙って無視して作業を続行する必要があります。

TCP通信にIndyを使用していますが、エラーメッセージが表示されないようにするためのすべての試み(つまり、クライアントに接続しているときにサーバーアプリケーションが閉じたとき)が失敗しました。

これを本当に堅牢にする方法はありますか?

現在のコードは次のようになります。

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で特に一般的です。)
  • 例外でプログラムを中断しないようにデバッガーを設定します。
  • 統合デバッグを完全に無効にします。

メッセージが実際にデバッガーではなくプログラムから送信されている場合は、戻ってデバッガーを使用して、メッセージの送信元を特定します。メッセージが表示されたら、プログラムを一時停止し、コールスタックウィンドウを見て、メッセージを表示しているコードの領域を見つけます。これは、表示したコードには明らかに含まれていないためです。EAccessViolation示したコードは、やなどのIndyに関連しないものも含め、すべての例外を完全に抑制しています(処理していません)EOutOfMemory

于 2009-06-12T15:18:29.077 に答える
2

Synapseパッケージを使用した単純なTCP通信タスクの場合、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

可能であれば、UDPの使用を検討してください。これは「コネクションレス型」であるため、送信者はメッセージを送信するだけで、受信アプリケーションはポートをリッスンしている場合にメッセージを受信します。ただし、サーバーが何らかの確認応答を送信しない限り、送信者は配信に関する確認を受け取りません。

于 2009-06-12T17:59:33.697 に答える
0

Harriv応答はOKです。UDP接続の動作を説明しています。私は同じような状況で使用しています。

于 2009-06-12T21:44:43.860 に答える
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 に答える