2017-02-09 5 views
-2

ここでは可能な解決策についてはどこにでも検索しましたが、私は成功していない回答をいくつか試しました。ソケットレスポンスCサーバーをJavaクライアントに読み取ることができません

シンプルなJava TCPソケットクライアントを実装しました。クライアントは1つのJavaサーバーでうまく動作しますが、Cでコード化されたサーバーからの応答を受信するのに問題があり続けます。 サーバーはトランザクションを正しく処理しているように見え、それに応じて応答を送信します。問題は、クライアントが応答の着信ストリームを受信できることにあります。 これは私の最初の実装だった:私はWiresharkのをダウンロードして、サーバソケットが待機している対応するポートでクライアントとサーバ間のTCPパケットのトラフィックを監視するためにそれを使用し

 String msg_out = message; 
     String reply; 

     //the stream object to transmit message to server 
     DataOutputStream outStream = new DataOutputStream(clientSocket.getOutputStream()); 

     outStream.writeBytes(msg_out + '\n'); 
     outStream.flush(); 

     //try to break away from locked read 
     //clientSocket.setSoTimeout(10000); 

     //initial implementation 
     //the object to receive reply server 
     BufferedReader replyStream = new BufferedReader(new InputStreamReader(clientSocket.getInputStream())); 
     reply = replyStream.readLine(); 

     System.out.println("Reply from "+ host + ":" + port + " -> " + reply); 

。私は、似たようなトピックを持つ他のスレッドで複数の提案を見ましたが、私は残念ながらそれらのソリューションのどれも私のために働くことができませんでした。私は、返信を含むパケットにフラグ値がPSHに設定されていることを発見しました。私は、Javaクライアントが応答をバッファリングしようとしていたため、このフラグのために接続がリセットされる(次のエラーパケットに表示されるRST)ことが考えられました。私はバイトでリプライバイトを読み取ろうとここのスレッドで見つかりましたが、無駄にこの実装でテストを試してみました:

try { 
      DataInputStream in = new DataInputStream(clientSocket.getInputStream()); 
      int bytesRead = 0; 
      byte[] messageByte = new byte[1000]; 
      boolean end = false; 
      String messageString = ""; 
      messageByte[0] = in.readByte(); 
      messageByte[1] = in.readByte(); 
      ByteBuffer byteBuffer = ByteBuffer.wrap(messageByte, 0, 2); 

      int bytesToRead = byteBuffer.getShort(); 
      System.out.println("About to read " + bytesToRead + " octets"); 

      //The following code shows in detail how to read from a TCP socket 

      while(!end) 
      { 
       bytesRead = in.read(messageByte); 
       messageString += new String(messageByte, 0, bytesRead); 
       if (messageString.length() == bytesToRead) 
       { 
        end = true; 
       } 
      } 


      System.out.println("Server Reply: " + messageString); 
     } catch (Exception e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 

私はCサーバのソースコードへのアクセスを持っていないが、その開発者はに誓います問題は彼の最後ではないと私は彼を信じている。私は彼がそれを変更することはできません知っているそれは、使用している他のすべてのクライアントアーキテクチャで動作するので、私はこのCベースのサーバーと対話する唯一のJavaクライアントの1つだと思います。私の実装にエラーがあるのですか、それとももっと愚かな方法で返信ストリームを読むために使用できる別の実装がありますか?

はここで、クライアント/サーバーのCOMMプロセスを実行しようとした結果です:

[2/10/17 14:23:49:658 EST] 00000031 SystemOut  O Outgoing transaction message:C00052!GDT43000KU!01!D-10!G-11!NORMAL!|     
[2/10/17 14:23:49:658 EST] 0000011e SystemOut  O Buffersize in stream:8192 
[2/10/17 14:23:49:737 EST] 0000011e SystemOut  O About to read 12336 octets 
[2/10/17 14:23:49:737 EST] 0000011e SystemErr  R java.net.SocketException: Connection reset 
[2/10/17 14:23:49:737 EST] 0000011e SystemErr  R  at java.lang.Throwable.<init>(Throwable.java:67) 
[2/10/17 14:23:49:737 EST] 0000011e SystemErr  R  at java.net.SocketInputStream.read(SocketInputStream.java:118) 
[2/10/17 14:23:49:737 EST] 0000011e SystemErr  R  at java.io.DataInputStream.read(DataInputStream.java:94) 
[2/10/17 14:23:49:737 EST] 0000011e SystemErr  R  at com.gf.btv.RTDLTSS.domain.LTSSClient.TCPClientRequest(LTSSClient.java:141) 
[2/10/17 14:23:49:737 EST] 0000011e SystemErr  R  at com.gf.btv.RTDLTSS.helper.LTSSClientThread.run(LTSSClientThread.java:147) 
[2/10/17 14:23:49:737 EST] 0000011e SystemErr  R  at java.lang.Thread.run(Thread.java:736) 
+0

Big Endianで送信してもよろしいですか?いくつかのCプログラムはリトルエンディアンを想定しています。 –

+1

*クライアントを実行しようとすると実際に何が起こりますか? – immibis

+1

サーバーは応答にどのプロトコルを使用していますか?それはバイトレベルで文書化されていますか?サーバーが何を期待しているのかわからない場合、クライアントが正しいことをしているかどうかをどうやって知ることができますか?プロトコルのリバースエンジニアリングが必要な場合は、サーバーが送信したバイト数を表示してください。 ) –

答えて

0

バイナリ読むために必要がある場合はRSTがPSHまたはバッファリーダーとは何かを持っているのではなく、読者は適切ではない。 RSTは、ピアからの読み取りを行う前にピアが接続を終了したことを示します。これは、間違ったプロトコルを使用していることを強く示しています。要求プロトコルが回線ベースであるが、応答プロトコルは長さ - 語 - 接頭語ベースであることは信用できない。どちらか一方、または他の何か。

int messageLength = in.readShort(); 
byte messageBytes = new byte[messageLength]; 
in.readFully(messageBytes); 
// etc. 

をしかし、あなたは実際のプロトコルの確認が必要になります。

あなたはそれが本当に長ワードプレフィックスプロトコルであると判断した場合は、これを試してみてください。推測はあなたをそこに連れてこないでしょう。

+0

私はエンディアンを認識していることを確認するようにもう一度質問しますが、問題はこれであるとは本当に思いません。 – rocklandcitizen

+0

*プロトコルを認識していることを再度確認する必要があります。*すでにここで2つ使用していますが、両方が正しいとは考えにくいでしょう。確かに*どちらも正しいわけではありません。 – EJP

+0

「短い」(2バイトのint)値は12336であり、それぞれASCII文字「0」を含む2バイトの値です。私は、サーバーが実際に文字の長さか他の値のいずれかを送信していると思われます。 –

関連する問題