web-dev-qa-db-ja.com

Java ServerSocket接続制限?

ソケットを使用していくつかのテストを実行していましたが、奇妙な動作が発生しました。ServerSocketは、50番目のクライアントソケットが接続した後、次のソケットが開かれる前にそのクライアントソケットが閉じられていても、遅延が発生しても接続を拒否します。接続間に追加されました。

次のプログラムは私の実験的なコードであり、現在の状態では例外をスローせず、正常に終了します。ただし、Socket[] clientsの配列サイズが50を超えて増加した場合、50番目の接続後に接続しようとするクライアントソケットはサーバーソケットによって拒否されます。

質問:50がサーバーソケットによってソケット接続が拒否されるカウントであるのはなぜですか?

public static void main(String[] args) {
    try (ServerSocket server = new ServerSocket(2123)) {
        Socket[] clients = new Socket[50];
        for (int i = 0; i < clients.length; i++) {
            clients[i] = new Socket("localhost", 2123);
            System.out.printf("Client %2d: " + clients[i] + "%n", i);
            clients[i].close();
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}

別の50個のソケットが別のローカルサーバーに接続するテストを実行しましたが、100個のソケットを開いたり閉じたりしても問題は発生しなかったため、サーバーソケットが接続を拒否しており、クライアントソケットを開く制限はないと推測しましたが、同時に接続されていないのに、サーバーソケットが50接続に制限されている理由を見つけることができませんでした。

11
FThompson

それはすべて JavaDoc にあります:

着信接続指示(接続要求)の最大キュー長は50に設定されています。キューがいっぱいになったときに接続指示が到着すると、接続は拒否されます。

どうやらあなたのServerSocketは接続を決して受け入れず、ただ聞くだけです。 accept()を呼び出して接続の処理を開始するか、バックログキューのサイズを増やす必要があります。

new ServerSocket(port, 100)
15

50はbacklogのデフォルト値です

http://docs.Oracle.com/javase/1.4.2/docs/api/Java/net/ServerSocket.html#ServerSocket%28int%29

着信接続指示(接続要求)の最大キュー長は50に設定されています。キューがいっぱいになったときに接続指示が到着すると、接続は拒否されます。

4
irreputable

@TomaszNurkiewiczの回答に従って、機能する例を次に示します。

import Java.net.*;
import Java.util.concurrent.atomic.AtomicBoolean;

public class SockTest{
public static void main(String[] args) {
    final AtomicBoolean shouldRun = new AtomicBoolean(true);
    try  {
        final ServerSocket server = new ServerSocket(2123);
        Thread serverThread = new Thread(){
           public void run() {
              try {
                 while(shouldRun.get()) {
                 Socket s = server.accept();
                 s.close();
             Thread.sleep(1);
                }
              } catch(Exception ex) {
                ex.printStackTrace();
              }
           }
        };
        serverThread.start();
        Socket[] clients = new Socket[150];
        for (int i = 0; i < clients.length; i++) {
            clients[i] = new Socket("localhost", 2123);
            System.out.printf("Client %2d: " + clients[i] + "%n", i);
            clients[i].close();
        }
        shouldRun.set(false);
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
       shouldRun.set(false);
    }

  }
}
2
GreyBeardedGeek

あなたが見るかもしれない2つのこと

  1. サーバーは接続を受け入れていません。
  2. サーバーは、同時に多くの接続に対応できません。バックログの増加(50を超える)が原因である可能性があります。サーバーに再度接続する前に、ミリ秒単位で時間間隔を空けてみてください。ランプアップ接続のように。テストロードを実行したときにタイムギャップを与えることで解決しました。
0
Jiten