Я пишу программу чата, используя сокеты и Java, и мне нужно указать порт, который слушают серверы.
Вот вопросы, которые у меня есть:
Как я могу быть уверен, что этот порт всегда свободен?
Имеет ли значение, прослушивает ли этот порт другая программа?
Если порт должен быть свободен, а порт по умолчанию занят, как я бы уведомил клиентов об изменении номера порта?
Должен ли я просто сделать так, чтобы сервер продолжал пытаться привязаться к новому порт, увеличивая номер порта до тех пор, пока не будет найден свободный порт?




How can I be sure that that port is always free?
Вы можете использовать netstat, чтобы проверить, доступен ли порт. Вы можете перечислить все порты, используемые службой, с помощью:
netstat -anp
Если вы хотите найти определенный порт, вы можете использовать:
netstat -anp | find "port number", например netstat -anp | find ":8080".
Does it matter if another program is also listening on that port?
Традиционно, да, для TCP вы можете иметь только одно приложение, прослушивающее один и тот же порт и один и тот же локальный IP-адрес одновременно. Вы можете использовать один и тот же порт, имея несколько локальных IP-адресов, используя несколько сетевых карт или виртуальных сетевых интерфейсов.
Однако, похоже, что, используя опцию сокета SO_REUSEPORT, вы можете повторно использовать ее, проверьте это для получения дополнительной информации.
If the port has to be free and the default port is occupied, how would I notify the clients of a change in port number? Should I just make it so the server keeps trying to bind to a new port, incrementing the port number until it finds a free port?
Лично я бы выбрал порт, который всегда свободен, или небольшой список портов, которые, как я знал, обычно будут бесплатными, и попробую один за другим.
Общие практические правила выбора порта включают выбор как минимум 4-значного числа и избегать всего, что меньше 1024. Кроме того, даже если порт уже использовался другой службой, вы можете переназначить его для прослушивания другого порта, в конце концов, его сети ваш.
Вы можете зарегистрировать свой порт в IANA. Вот список уже используемых портов.
https://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.txt
Ты можешь подумать
hey, I am a single person only! I dont like to threat a international authority!
Имейте в виду, что:
2031, и человек, который зарегистрировал порт, является частным лицом, а не программистом (и, возможно, уже мертв сегодня).Не могли бы вы описать архитектуру, которую вы пытаетесь построить? Где вы запускаете свой сервер и клиентов?
Мои предложения:
Используйте один постоянный порт и настройте веб-сервер (например, - nginx) для маршрутизации запросов на этот порт в соответствии с доменом. Клиентам не нужно знать порты - только домен. Кроме того, это позволит не открывать для сети все порты - только те, которые необходимы (80, 443).
При запуске попробуйте определить свободный порт (вызовите netstat или просто увеличьте номер порта до тех пор, пока служба не будет запущена), сохраните номер порта в локальном файле. Отправьте этот локальный файл с помощью веб-сервера - например, nginx - всегда порт 80 или 443 - как статические данные. Клиенты сначала получат номер порта по статическому URL-адресу, а затем подключатся к предоставленному порту.
Используйте службу имен - например, - Spring Cloud - запускайте на отдельном сервере. Откройте для себя свободный порт при запуске приложения, зарегистрируйте его в службе имен. Клиенты всегда сначала запрашивают услугу присвоения имен. В качестве альтернативы вы можете просто использовать простой балансировщик (например, AWS Elastic Balancer + AWC EC2).
Используйте Kubernetes - настройте «Службу» на определенном порту и запустите любое количество экземпляров вашего приложения в подах - свободные порты будут обнаружены автоматически.
P.s. Вы не можете запускать несколько приложений на одном порту. Скорее всего даже не запустится.
Если это сервер ваш, на котором работает программа, ты должен решить, какой порт использовать, и убедиться, что он доступен (т.е.не используется другой программой). Чтобы проверить это, просто попробуйте bind() вашего ServerSocket на этом порту. Если вы получаете IOException, вероятно, порт уже используется (в Linux проверьте вывод netstat -anp | grep <port>, чтобы узнать, какая программа его использует).
Если вы не хотите / не можете использовать фиксированный порт, вы всегда можете выполнить привязку к порту 0, который автоматически назначит свободный порт. Затем вы можете получить назначенный порт с помощью getLocalPort().
Однако для того, чтобы клиенты могли подключиться к вашему серверу (который работает на «плавающем» порте), вам необходимо прорекламировать его, например через JNDI (предпочтительно в Java), LDAP, ... (см. примеры @Azee ответ).
В качестве побочного примечания обратите внимание, что TCP-параметры SO_REUSEADDR / SO_REUSEPORTимеют ли нет то же значение, в зависимости от используемой вами ОС (не говоря уже об их (не) доступности).