2011-12-23 29 views
2

クライアントサーバーからリモートサーバーへの接続をミラーリングするJavaプログラムがあります。ミラーはデータを検索しますが、受信しません。なぜ私は私の人生のために理解することはできません。ここに私のコードは次のとおりです。ソケットミラーは送信しますが受信しません

Socket client = new Socket("127.0.0.1", 42001); 
System.out.println("Connected to client!"); 
Socket server = new Socket(serverAddress, serverPort); 
System.out.println("Connected to server!"); 

BufferedReader clientin = new BufferedReader(new InputStreamReader(client.getInputStream())); 
BufferedWriter scratchout = new BufferedWriter(new OutputStreamWriter(client.getOutputStream())); 

BufferedReader serverin = new BufferedReader(new InputStreamReader(server.getInputStream())); 
BufferedWriter serverout = new BufferedWriter(new OutputStreamWriter(server.getOutputStream())); 

int i; 
boolean serverNeedsFlush = false; 
boolean clientNeedsFlush = false; 
while (true) 
{ 
    while (clientin.ready()) 
    { 
     i = clientin.read(); 
     serverout.write(i); 
     serverNeedsFlush = true; 
    } 
    if(serverNeedsFlush) 
    { 
     serverout.flush(); 
     serverNeedsFlush = false; 
    } 
    while (serverin.ready()) 
    { 
     i = serverin.read(); 
     System.out.print((char)i); 
     scratchout.write(i); 
     clientNeedsFlush = true; 
    } 
    if(clientNeedsFlush) 
    { 
     scratchout.flush(); 
     clientNeedsFlush = false; 
    } 
} 
+0

2つのスレッドを使用している場合、ビジー待機または読み込みラインをまったく必要としません。取得したデータをコピーするだけです。 –

答えて

1

あなたは別のソケットからのデータを転送しようとした場合、おそらく、ソケットストリームを使用し、直接ではなく、それらを飾るために良いアイデアだろう。

他のポスターが示唆しているように、これを行うにはスレッドを使用する必要があります。それは人生を楽にします。次に、スレッドを使用して、以下のように基本ストリームからストリームストリームへのコピーを行うことができます。戻って上記の方法は、あなたが全体inストリームを読み、outストリームでそれを書かれているだろう

public static void streamCopy(InputStream in, OutputStream out) 
     throws IOException{ 

     byte[] data = new byte[1024]; 
     int length; 
     do{ 
      length = in.read(data); 
      if(length > 0){ 
       out.write(data, 0, length); 
       out.flush(); 
      } 
     }while(length != -1); 

} 

。スレッドまたは実行可能ファイルのrunメソッドは、次のようになります。

public void run() { 

    Socket inSock = null; 
    Socket outSock = null; 
    try{ 
     inSock = new Socket(inHost, inPort); 
     outSock = new Socket(inHost, inPort); 
     /* Set up some socket options here (timeouts, buffers etc)*/ 

     /* Insert pre copy actions */ 

     /* This method won't return until inSock's inputStream hits end of stream. 
     * and all the data has been written to outSock's outputStream and flushed. */ 
     streamCopy(inSock.getInputStream(), outSock.getOutputStream()); 

     /* In order to really do this correctly you should create an 
     * application protocol that verifies the upstream receiver 
     * is actually getting the data before you close the socket. */ 

     /* Insert post copy actions */ 

    }catch(Exception e){ 
     /* Corrective action or logging here */ 
    }finally{ 
     /* Don't forget to close the sockets. */ 
     if(inSock != null){ 
      try{ 
       inSock.close(); 
      }catch(Exception e){ 
       /* Don't care */ 
      } 
     } 
     if(outSock != null){ 
      try{ 
       outSock.close(); 
      }catch(Exception e){ 
       /* Don't care */ 
      } 
     } 
    } 
} 
+0

flushを呼び出すと、何も実行されませんが、何もしません。フラグを設定する必要はありません。 –

+0

'length = clientin.read(data);'と書くだけで、まったく同じことができます。 –

+0

@Peter 'length = clientin.read(data);'が利用可能なバッファとブロックを越えて読み込もうとしたら、明示的に長さを渡して利用可能なバッファと読み込みのみを読み込むようにしました。私はそれがOPのコードからコピーの貼り付けだったので、フラッシュ部分の良い呼び出し、私はそれを逃した。 – Dev

1

これは、1つのスレッドで適切に行うことはできません。各方向に1つずつ、2つのスレッドが必要です。各スレッドは、EOSに出会うまで読み書きを行います。 available()を使わないでください:読み込みをブロックするだけです。病理学的な状況を避けるために、読み取りタイムアウトを設定してください。

関連する問題