1

Linux システムでソケット通信の問題が発生しました。通信プロセスは次のようになります。クライアントはメッセージを送信してサーバーに計算タスクを実行するように依頼し、タスクの完了後にサーバーからの結果メッセージを待ちます。

ただし、サーバー側からはクライアントに応答するために結果メッセージがソケットに書き込まれていても、タスクに約 40 分かかる場合、クライアントは結果メッセージを待つためにハングアップします。 1 分など、タスクにほとんど時間がかからない場合は、結果メッセージを受け取ります。また、この問題はお客様の環境でのみ発生し、通信プロセスはテスト環境で正常に動作します。

この問題の原因は、ソケットのデフォルトのタイムアウト値がお客様の環境とテスト環境で異なるためではないかと推測していますが、以下の値はこれら 2 つの環境、およびクライアントとサーバーの両方で同じです。

getSoTimeout:0
getReceiveBufferSize:43690
getSendBufferSize:8192
getSoLinger:-1
getTrafficClass:0
getKeepAlive:false
getTcpNoDelay:false

クライアントのコードは次のようになります。

Message msg = null;
ObjectInputStream in = client.getClient().getInputStream();
//if no message readObject() will hang here
while ( true ) {
  try {
   Object recObject = in.readObject();
   System.out.println("Client received msg.");
   msg = (Message)recObject; 
   return msg;
       }catch (Exception e) {
    e.printStackTrace();
    return null;
   }
}

サーバー上のコードは次のようになります。

ObjectOutputStream socketOutStream = getSocketOutputStream();
try {
  MessageJobComplete msgJobComplete = new MessageJobComplete(reportFile, outputFile );
  socketOutStream.writeObject(msgJobComplete);
  }catch(Exception e) {
    e.printStackTrace();
  }

この問題を解決するために、フラッシュとリセットの方法を追加しましたが、問題はまだ存在します:

ObjectOutputStream socketOutStream = getSocketOutputStream();
try {
   MessageJobComplete msgJobComplete = new MessageJobComplete(reportFile, outputFile );
   socketOutStream.flush();
   logger.debug("AbstractJob#reply to the socket");
   socketOutStream.writeObject(msgJobComplete);
   socketOutStream.reset();
   socketOutStream.flush();
   logger.debug("AbstractJob#after Flush Reply");
 }catch(Exception e) {
    e.printStackTrace();
            logger.error("Exception when sending MessageJobComplete."+e.getMessage());
 }

この問題を解決するために私が次に何をすべきかを知っている人はいますか。原因は環境設定だと思いますが、どのような環境要因がソケット通信に影響を与えるのかわかりませんか?

また、Tcp/Ip プロトコルを使用して通信するソケットの問題は、長時間のタスクに関連しているため、tcp に関するどの値がソケット通信のタイムアウトに影響しますか?

ログについて分析したところ、メッセージがソケットに書き込まれた後に例外がスロー/キャッチされていないことがわかりました。ただし、常に 15 分後に、クライアントからの要求を受け入れるために使用されるサーバー側の objectInputStream.readObject() コード スニペットに例外があります。ただし、socket.getSoTimeout の値が 0 であるため、タイムアウト例外がスローされたのは非常に奇妙です。

{2012-01-09  17:44:13,908} ERROR java.net.SocketException: Connection timed out
   at java.net.SocketInputStream.socketRead0(Native Method)
   at java.net.SocketInputStream.read(SocketInputStream.java:146)
   at sun.security.ssl.InputRecord.readFully(InputRecord.java:312)
   at sun.security.ssl.InputRecord.read(InputRecord.java:350)
   at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:809)
   at sun.security.ssl.SSLSocketImpl.readDataRecord(SSLSocketImpl.java:766)
   at sun.security.ssl.AppInputStream.read(AppInputStream.java:94)
   at sun.security.ssl.AppInputStream.read(AppInputStream.java:69)
   at java.io.ObjectInputStream$PeekInputStream.peek(ObjectInputStream.java:2265)
   at java.io.ObjectInputStream$BlockDataInputStream.peek(ObjectInputStream.java:2558)
   at  java.io.ObjectInputStream$BlockDataInputStream.peekByte(ObjectInputStream.java:2568)
   at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1314)
   at java.io.ObjectInputStream.readObject(ObjectInputStream.java:368)

では、なぜ Connection Timed out 例外がスローされるのでしょうか?

4

2 に答える 2

2

この問題は解決されました。を使用しtcpdumpてメッセージフローをキャプチャします。アプリケーションレベルではObjectOutputStream.writeObject()メソッドが呼び出されていましたが、tcpレベルでは何度[TCP ReTransmission]も見つかりました。

netstat -anしたがって、コマンドを使用するとtcp接続状態はまだでしたが、接続が切断されている可能性があると結論付け ましたESTABLISHED

そこで、サーバーからハートビートメッセージとしてテストメッセージを定期的に送信するテストアプリケーションを作成しました。その後、この問題は解消されました。

于 2012-02-09T06:29:13.617 に答える
1

read()メソッドは呼び出しjava.io.InputStreamブロックしています。つまり、ストリームに読み取るデータがないときに呼び出された場合、「永久に」待機します。

これは完全に予想される動作であり、サーバーが応答しない場合はjavadocで公開されているコントラクトに従います。

ノンブロッキング読み取りが必要な場合は、java.nio.*クラスを使用してください。

于 2012-01-10T05:38:16.073 に答える