2
  • 我使用端口 9000 启动使用 Jetty 服务器的应用程序。
  • 然后我用 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 服务器之前以某种方式避免它吗?

编辑 #1这是我们创建 BlockingChannelConnector 的代码,注意“setReuseAddress(true)”:

    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 文件时,上述问题会重复出现。威士忌探戈狐步舞?

编辑#3(4天后) -仍然有问题。有什么想法吗?

4

4 回答 4

3

During your first invocation of your program, did it accept at least one incoming connection? If so then what you are most likely seeing is the socket linger in effect.

For the best explanation dig up a copy of TCP/IP Illustrated by Stevens

alt text
(source: kohala.com)

But, as I understand it, because the application did not properly close the connection (that is BOTH client and server sent their FIN/ACK sequences) the socket you were listening on cannot be reused until the connection is considered dead, the so called 2MSL timeout. The value of 1 MSL can vary by operating system, but its usually a least a minute, and usually more like 5.

The best advice I have heard to avoid this condition (apart from always closing all sockets properly on exit) is to set the SO_LINGER tcp option to 0 on your server socket during the listen() phase. As freespace pointed out, in java this is the setReuseAddress(true) method.

于 2008-09-19T13:48:14.520 回答
1

You might want call setReuseAddress(true) before calling bind() on your socket object. This is caused by a TCP connection persisting even after the socket is closed.

于 2008-09-19T13:42:24.363 回答
0

我必须说我也认为这是 setReuseAddress(true) 解决的常见问题。但是,这种情况下的错误消息通常是 JVM 无法绑定到端口的内容。我以前从未见过发布的错误消息。谷歌搜索似乎表明另一个进程正在侦听一个或多个(但不是全部)网络接口,并且您请求您的进程绑定到所有接口,而它可以绑定到一些(其他进程未侦听的接口) to) 但不是全部。只是在这里猜测......

于 2008-09-19T20:11:57.267 回答
0

I'm not sure about Jetty, but I have noticed that sometimes Tomcat will not shut down cleanly on some of our Linux servers. In cases like that, Tomcat will restart but not be able to use the port in question because the previous instance is still bound to it. In such cases, we have to find the rogue process and explicitly kill -9 it before we restart Tomcat. I'm not sure if this is a java bug or specific to Tomcat or the JVM we're using.

于 2008-09-19T13:47:00.840 回答