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

プログラムの最初の呼び出し時に、少なくとも 1 つの着信接続を受け入れましたか? もしそうなら、あなたが見ている可能性が最も高いのは、有効なソケットの残留です。

最良の説明については、Stevens による TCP/IP Illustrated のコピーを掘り起こします

代替テキスト
(出典: kohala.com )

しかし、私が理解しているように、アプリケーションが接続を適切に閉じなかった (つまり、クライアントとサーバーの両方が FIN/ACK シーケンスを送信した) ため、接続が切断されたと見なされるまで、リッスンしていたソケットを再利用できません。いわゆる 2MSLタイムアウト。1 MSL の値はオペレーティング システムによって異なりますが、通常は少なくとも 1 分で、通常は 5 程度です。

この状態を回避するために私が聞いた最善のアドバイスは (終了時に常にすべてのソケットを適切に閉じることは別として)、listen() フェーズでサーバー ソケットの SO_LINGER tcp オプションを 0 に設定することです。freespace が指摘したように、Java ではこれは setReuseAddress(true) メソッドです。

于 2008-09-19T13:48:14.520 に答える
1

ソケット オブジェクトを呼び出すsetReuseAddress(true)前にcall が必要になる場合があります。bind()これは、ソケットが閉じられた後も TCP 接続が持続することが原因です。

于 2008-09-19T13:42:24.363 に答える
0

setReuseAddress(true) によって解決される通常の問題だとも思ったと言わざるを得ません。ただし、その場合のエラー メッセージは通常、JVM がポートにバインドできないという内容です。以前に投稿されたエラー メッセージを見たことがありません。グーグルで検索すると、別のプロセスが1つ以上の(ただしすべてではない)ネットワークインターフェイスでリッスンしていることを示唆しているようで、プロセスにすべてのインターフェイスにバインドするように要求しますが、一部のインターフェイス(他のプロセスがリッスンしていないもの)にバインドできますに)しかし、それらのすべてではありません。ここは推測ですが…

于 2008-09-19T20:11:57.267 に答える
0

Jetty についてはよくわかりませんが、一部の Linux サーバーで Tomcat が正常にシャットダウンしない場合があることに気付きました。このような場合、Tomcat は再起動しますが、以前のインスタンスがまだバインドされているため、問題のポートを使用できません。このような場合、Tomcat を再起動する前に、不正なプロセスを見つけて明示的に kill -9 する必要があります。これが Java のバグなのか、Tomcat や使用している JVM に固有のものなのかはわかりません。

于 2008-09-19T13:47:00.840 に答える