2009-08-27 14 views
31

出力ストリームのソケットにしか書いていない場合は、これはブロックされますか?読み取りだけがブロックできますか?誰かが書き込みがブロックすることができると私に言ったが、私はソケットの読み取りメソッドのためのタイムアウト機能 - Socket.setSoTimeout()を参照してください。Javaソケット/出力ストリーム書き込み:ブロックしますか?

書き込みがブロックされる可能性はありません。

+0

タイムアウト機能が存在しないという事実は、それがブロックしていないことを示し、それ自体ではありません。戻り値がないことを示す1つの指示:ブロックされない場合、実際に書き込まれたバイト数は返されないのはなぜですか?もう一つの示唆はそれを試してみるだけです。 – EJP

答えて

45

ソケットの書き込みも、特にTCPソケットの場合はブロックできます。 OSは、ある量の未送信(または送信されたが未確認の)データのみをバッファします。リモートアプリが読み込める速度よりも速く書き込むと、ソケットは最終的にバックアップされ、writeコールはブロックされます。これらのフォローアップの質問に応え

だから、このため タイムアウトを設定するための仕組みがありますか?私はバッファーがいっぱいであれば のデータが捨てられるかもしれないと確信しています。または、おそらく バッファ内の古いデータを削除しますか?

java.net.Socketに書き込みタイムアウトを設定するメカニズムはありません。 Socket.setSoTimeout()メソッドがありますが、accept()read()コールには影響しますが、write()コールには影響しません。どうやら、NIO、ノンブロッキングモード、セレクタを使用すると、書き込みタイムアウトが発生する可能性がありますが、これは想像以上に有用ではありません。

正しく実装されたTCPスタックは、接続が閉じられていない限り、バッファリングされたデータを破棄しません。しかし、書き込みタイムアウトが発生すると、現在OSレベルのバッファにあるデータが相手側で受信されたかどうかは不明です。もう1つの問題は、最後のwriteのデータが実際にOSレベルのTCPスタックバッファにどれだけ転送されたかわからないことです。 *のストリームを再同期化するためのアプリケーションレベルのプロトコルがない場合、writeのタイムアウト後に行う唯一の安全な作業は、接続をシャットダウンすることです。

UDPソケットを使用している場合、write()コールはかなりの時間ブロックされません。しかし、欠点は、ネットワークに問題がある場合や、リモートアプリケーションが追いついていない場合、メッセージがどちらの端末にも通知されずにフロアにドロップされることです。また、メッセージがリモートアプリケーションに順不同で配信されることがあります。これらの問題に対処するのはあなた(開発者)次第です。

*これは理論的には可能ですが、ほとんどのアプリケーションでは、すでに信頼できる(ポイントへの)TCP/IPストリームの上に追加の再同期メカニズムを実装することは意味がありません。そして、それが理にかなっていれば、接続が閉じられた可能性にも対処する必要があります。とする方が簡単です。

+0

これにタイムアウトを設定するメカニズムはありますか?私はどのような振る舞いがあるのか​​分かりません。バッファがいっぱいになったらデータを捨てるかもしれません。または、バッファ内の古いデータを削除する可能性がありますか? – jbu

+0

テストのためにこれを再現する方法はありますか?私は自分のアプリケーションをこれから回復できるようにしたい。このために私はテストが必要 – Zamir

+0

AFAIK、一般的な方法はありません。しかし、アプリケーションの性質(例えば、何を話しているか)によっては、さまざまな方法があります。新しい質問をして、具体的にしてください。 –

関連する問題