2010-12-02 7 views
1

私は、Javaを使用してマルチスレッドのTCPサーバ - クライアントアプリケーションを実装しています。しかし、今私は奇妙な問題に遭遇しました。サーバーソケットをシャットダウンすると、受信者は最後に送信されたパケットを引き続き受信できます。ソケット読み込みの詳細はカーネルの関心事なので、私はその理由を理解することはできません。誰か指針を与えることはできますか? ありがとうございます! 編集:関与 コードは単純である:ソケットサーバーがシャットダウンした後にTCP受信者がデータを受信できる理由

public void run() { 
    while(runFlag) { 
     //in = socket.getSocketInputStream(); 
     //byte[] buffer = new byte[bufferSize]; 
     try { 
      in.read(buffer); 
      //process the buffer; 
     }catch(IOException e) { 
      // 
     } 
    } 
} 

シャットダウンサーバーソケットは、この読み出し動作は、(各時間whileループに入る)を連続的にパケットを受信する場合。

答えて

2

データがすでにクライアントソケットのバッファ(カーネルレベル、アプリケーションがユーザー空間のメモリに読み込むのを待っている)にある場合、サーバーがそのデータを読み取らないようにする方法はありません。それはカタツムリの郵便のようです。一度それを送ってしまえば元に戻すことはできません。

+0

データがすでに*送信側の*ソケットバッファに入っている場合、データはまだFINより先に送信されます。 – EJP

+0

「FIN」の意味は何ですか? –

+0

これがこの接続の最終パケットであることを示す*単一ビット*です。 – EJP

3

OS内のTCP/IPスタックは、接続の両側のデータをバッファリングするです。 Senderは、ソケット送信バッファーを埋め込みます。これは、デバイスドライバーがパケットをワイヤーにプッシュすることによって排出されます。レシーバは、ソケット受信バッファのワイヤからパケットを蓄積します。このパケットは、アプリケーションの読み込みによって流出します。

+0

@ThiefMaster、@Nikolai N Fetissovありがとうございました。問題はクライアントのバッファーで発生したようです。しかし、なぜ私はまだよく分からないのです(なぜin.read(バッファ)がカーネルバッファを消費しないのですか?) –

+0

あなたのコードを投稿してください。 –

+0

問題?何の問題? – EJP

0

これがTCPの動作です。これは信頼できるバイトストリームです。引き渡されていないデータは、通常のクローズ後も引き続き配信されます。あなたが望むものではありませんか?なぜこれは「問題」ですか?

+0

私はそれを明確にしていないと申し訳ありません。 'problem'は、クライアントの読み取り操作が、最後に送信されたパケットを常に読み取ることに成功することを意味します(毎回同じパケットを取得するのではなく、読み込みをブロックするか例外を投げるのが理にかなっていると思います)。私は私の質問を編集した、多分あなたはそれを見て与えることができます。 –

+0

in.read()の結果を無視しているというエラーがあります。 -1を返すと、ピアは接続を閉じたので、ソケットを閉じてループを終了する必要があります。バッファがいっぱいでない可能性も無視しています。これはbuffer.lengthより小さいread()からの正の戻り値によって示され、コードはとにかく動作しません。 – EJP

+0

ありがとうございました!本当に役に立ちます。 read()の戻り値を無視するのは私のせいです。しかし、私がしようとしたのは、ネットワーク状態の表示とプログラムのワークフローの制御のためにread()によってスローされた例外を利用することです。 java APIのdocsによると、ストリームの終わりが検出された場合はread()が-1を返し、IOExceptionをスローします。 "ファイルの終わり以外の理由で最初のバイトを読み取れない場合は、またはその他のI/Oエラーが発生した場合に発生します。なぜサーバーをシャットダウンすると、このコードのread()が例外をスローしないのですか? –

関連する問題