あなたの友人は正しいですが、それはどのようにしてtcpipプロトコルが動作するかに関係します。クライアントに送信されるパケットを大幅に単純化する必要があります。クライアントが応答していない場合(受信データの読み取りに失敗し、コンピュータの負荷が高いなど)、サーバーは確認応答を受信せず、データの送信を停止します。 TCP/IPに組み込まれているこのメカニズムは、通信の一方の端が大量のデータを送信することを防止し、他方の端が受信したことを確認しません。これにより、大量のデータを再送信する必要がなくなります。
Javaでは、これはブロッキング書き込みとしてOutputStream
に現れます。基礎となるTCP/IPスタック/オペレーティングシステムでは、クライアントがデータを受信する準備ができるまで、より多くのデータを送信することはできません。
これは簡単にテストできます。私は、接続を受け入れますが、受信データの読み取りに失敗し、単純なサーバーを実装:
new Thread(new Runnable() {
@Override
public void run() {
try {
final ServerSocket serverSocket = new ServerSocket(4444);
final Socket clientSocket = serverSocket.accept();
final InputStream inputStream = clientSocket.getInputStream();
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
そして、ちょうど4Kバッチで、それはできるだけ多くのデータを送信し、簡単なクライアント:
final Socket client = new Socket("localhost", 4444);
final OutputStream outputStream = client.getOutputStream();
int packet = 0;
while(true) {
System.out.println(++packet);
outputStream.write(new byte[1024 * 4]);
}
クライアントループがオンにハングアップします私のコンピュータは95回の繰り返しの後で(あなたの走行距離は異なるかもしれません)。しかし、サーバスレッドでinputStream
から読んだ場合、ループが繰り返し実行されます。
スレッドの実行機能で出力ストリームまたは入力ストリームを取得しようとすると、同様の問題が発生しました。ソケットのgetInputStreamとgetOutputStreamの両方に対するブロッキングの問題は、実行関数内にあるためです。解決策はコンストラクタに変数を保存してから、変数を実行中に参照することです。 – Zimm3r