2008-09-19 5 views
2
  • Я начинаю мое приложение, которое использует сервер Jetty, используя порт 9000.
  • Я тогда закрыл мое приложение с помощью Ctrl-C
  • я проверяю с «NETSTAT -a» и увидеть, что порт 9000 больше не используется.
  • перезапустить мое приложение и получить:
[ERROR,9/19 15:31:08] java.net.BindException: Only one usage of each socket address (protocol/network address/port) is normally permitted 
[TRACE,9/19 15:31:08] java.net.BindException: Only one usage of each socket address (protocol/network address/port) is normally permitted 
[TRACE,9/19 15:31:08]  at java.net.PlainSocketImpl.convertSocketExceptionToIOException(PlainSocketImpl.java:75) 

[TRACE,9/19 15:31:08]  at sun.nio.ch.Net.bind(Net.java:101) 
[TRACE,9/19 15:31:08]  at sun.nio.ch.ServerSocketChannelImpl.bind(ServerSocketChannelImpl.java:126) 
[TRACE,9/19 15:31:08]  at sun.nio.ch.ServerSocketAdaptor.bind(ServerSocketAdaptor.java:77) 
[TRACE,9/19 15:31:08]  at org.mortbay.jetty.nio.BlockingChannelConnector.open(BlockingChannelConnector.java:73) 

[TRACE,9/19 15:31:08]  at org.mortbay.jetty.AbstractConnector.doStart(AbstractConnector.java:285) 
[TRACE,9/19 15:31:08]  at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:40) 
[TRACE,9/19 15:31:08]  at org.mortbay.jetty.Server.doStart(Server.java:233) 
[TRACE,9/19 15:31:08]  at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:40) 
[TRACE,9/19 15:31:08]  at ... 

Является ли это Java ошибка? Могу ли я как-то избежать этого перед запуском сервера Jetty?Почему я получаю «java.net.BindException: только одно использование каждого адреса сокета», если netstat говорит что-то еще?

Редактировать # 1 Вот наш код для создания нашего BlockingChannelConnector, обратите внимание на "setReuseAddress (истинный)":

connector.setReuseAddress(true); 
    connector.setPort(port); 
    connector.setStatsOn(true); 
    connector.setMaxIdleTime(30000); 
    connector.setLowResourceMaxIdleTime(30000); 
    connector.setAcceptQueueSize(maxRequests); 
    connector.setName("Blocking-IO Connector, bound to host " + connector.getHost()); 

Может иметь что-то делать с простоем?

Редактировать # 2 Следующий фрагмент головоломки, который может или не может помочь: при запуске приложения в режиме отладки (Eclipse) сервер запускается без проблем !!! Но описанная выше проблема возникает воспроизводимо при запуске приложения в режиме запуска или в виде встроенного файла jar. Виски Tango Foxtrot?

Редактировать # 3 (4 дня спустя) - все еще есть проблема. Есть предположения?

+0

Есть ли у вашей машины несколько интерфейсов? Если да, то какой из них вы связываете, и на каком интерфейсе был netstat -a? – freespace 2008-09-19 16:26:52

ответ

1

Возможно, вам понадобится позвонить setReuseAddress(true), прежде чем звонить bind() на ваш объект сокета. Это связано с тем, что TCP-соединение сохраняется даже после закрытия сокета.

+0

, мы вызываем это на BlockingChannelConnector. см. отредактированный вопрос – Epaga 2008-09-19 13:51:03

0

Я не уверен в Jetty, но я заметил, что иногда Tomcat не будет закрываться на некоторых наших Linux-серверах. В подобных случаях Tomcat перезапустится, но не сможет использовать данный порт, потому что предыдущий экземпляр все еще привязан к нему. В таких случаях мы должны найти процесс изгоев и явно убить -9 перед перезагрузкой Tomcat. Я не уверен, что это ошибка Java или специфическая для Tomcat или JVM, которую мы используем.

+0

, процесс по-прежнему не выполняется после его закрытия с помощью Ctrl-C. Фактически мы используем одно и то же окно консоли для запуска нового процесса. – Epaga 2008-09-19 13:54:03

3

Во время вашего первого вызова вашей программы он принял хотя бы одно входящее соединение? Если это так, то, что вы, скорее всего, видите, - это задержка сокета.

Для лучшего объяснения выкопать копию протокола TCP/IP Illustrated Стивенсом

alt text http://www.kohala.com/start/gifs/tcpipiv1.gif

Но, как я понимаю, потому что приложение не правильно закрывать соединение (то есть клиент и сервер отправил свои последовательности FIN/ACK), сокет, который вы слушали, не может быть повторно использован до тех пор, пока соединение не будет считаться мертвым, так называемый тайм-аут 2MSL. Значение 1 MSL может варьироваться в зависимости от операционной системы, но обычно оно меньше минуты и обычно больше похоже на 5.

Лучший совет, который я слышал, чтобы избежать этого условия (за исключением того, что он всегда закрывает все разъемы надлежащим образом при выходе) - установить для параметра SO_LINGER tcp значение 0 в гнезде вашего сервера во время фазы listen(). Как указывал freespace, в java это метод setReuseAddress (true).

+0

нет связь не принимается. Запустите, сразу же выключитесь. – Epaga 2008-09-19 13:54:35

0

Должен сказать, что я также думал, что это обычная проблема, решаемая setReuseAddress (true). Однако сообщение об ошибке в этом случае обычно является чем-то вроде строк, которые JVM не может связывать с портом. Я никогда не видел опубликованное сообщение об ошибке раньше. Похоже, Google-поиск предполагает, что другой процесс прослушивает один или несколько (но не все) сетевых интерфейсов, и вы запрашиваете свой процесс для привязки ко всем интерфейсам, тогда как он может связываться с некоторыми (те, которые другой процесс не прослушивает к), но не все из них. Просто гадать здесь, хотя ...