Ограничение соединения Java ServerSocket?

Я запускал несколько тестов с сокетами, и я столкнулся с каким-то странным поведением: ServerSocket откажется от соединений после того, как 50-й клиент Socket подключится к нему, даже если этот клиентский сокет закрыт до того, как откроется следующий, и даже если между соединениями добавляется задержка.

Следующая программа - это мой экспериментальный код, который в своем текущем состоянии не отменяет никаких исключений и обычно заканчивается. Однако, если размер массива 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 соединениями, хотя они не подключены одновременно.

Ответ 1

Все это в JavaDoc:

Максимальная длина очереди для входящих указаний на подключение (запрос для подключения) устанавливается равной 50. Если при завершении очереди появляется индикация соединения, соединение отказывается.

По-видимому, ваш ServerSocket никогда не принимает никаких подключений, просто слушает. Вы должны либо позвонить accept(), либо начать обработку соединения или увеличить размер очереди для отставания:

new ServerSocket(port, 100)

Ответ 2

50 является значением по умолчанию для backlog

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

Максимальная длина очереди для входящих указаний на подключение (запрос для подключения) установлена ​​равной 50. Если при завершении очереди появляется индикация соединения, соединение отказывается.

Ответ 3

Вот пример, который работает в соответствии с @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);
    }

  }
}

Ответ 4

Две вещи, которые вы можете посмотреть на

  • Сервер не принимает соединение.
  • Сервер не может обслуживать слишком много соединений в одном экземпляре. Это может быть вызвано увеличением отставания (выше 50). Попробуйте дать промежуток времени в миллисекундах, прежде чем снова подключиться к серверу. Как наращивание соединений. Я решил это, дав некоторый промежуток времени при запуске тестовой нагрузки.