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