6

Windows で別のプロセスが既にバインドされているソケットに Java アプリがバインドされないようにするにはどうすればよいですか?

ポート 80 でリッスンしている Java アプリケーションがあるという問題があります。アプリケーションは正常に起動し、例外は報告されません。ポート 80 に接続できなかった理由がわかりませんでした。他のポートは正常に機能していました。80 でリッスンしている他のプロセスの netstat を確認したところ、Skype が見つかりました。私はそれが可能だとは思いませんでしたが、いくつかの調査の結果、Skype は SO_REUSEADDR オプションでリッスンしていると推測しています。この状態では受理申請は不定です。このインスタンスで Java アプリケーションがバインド例外 (またはその他) で失敗することを望みます。

Java 経由でそのオプションにアクセスできれば SO_EXCLUSIVEADDRUSE を使用できるように見えますが、それは可能ではないと思います。SO_REUSEADDR に関する多くの質問と回答がありますが、私の質問に答えるものは見つかりませんでした。これは Skype だけの問題ではありません (リスニング部分をオフにすることができます)。この状況でプログラムをより堅牢にしたいと考えています。

これは、Windows 7 ボックスでの netstat -abn のスニペットです。

    Proto  Local Address          Foreign Address        State
    TCP    0.0.0.0:80             0.0.0.0:0              LISTENING [java.exe]
    TCP    0.0.0.0:80             0.0.0.0:0              LISTENING [Skype.exe]

これが、Skype が SO_REUSEADDR を使用していると想定している理由です。

プロセスは、異なるインターフェイスでリッスンしているようには見えません。

コードのスニペットを次に示します。ポートは 80 です。

    myServerSocket = new ServerSocket(myTcpPort);
    while (true) {
        new HTTPSession( myServerSocket.accept(), threadPool );
    }

さらに詳しい情報として、副作用や誤ったメッセージの処理を最小限に抑えるためのサンプル プログラムを作成しました。

    import java.net.ServerSocket;

    public class PortTest
    {
        public static void main(String[] args)
        {
            System.out.println( "Hit Ctrl-C to stop.\n" );

            try {
                ServerSocket myServerSocket = new ServerSocket(80);
                System.out.println( "Before the accept() call.");
                myServerSocket.accept();
                System.out.println( "After the accept() call." );
            }
            catch (Exception ex ) {
                System.out.println("Error listening.");
                ex.printStackTrace();
            }
         }

    }

このサンプル プログラム (PortTest) を実行しても、Skype が実行されていてポート 80 でリッスンしている場合でも、例外は発生しません。

    Error listening.
    java.net.BindException: Address already in use: JVM_Bind
            at java.net.DualStackPlainSocketImpl.bind0(Native Method)
            at java.net.DualStackPlainSocketImpl.socketBind(Unknown Source)
            at java.net.AbstractPlainSocketImpl.bind(Unknown Source)
            at java.net.PlainSocketImpl.bind(Unknown Source)
            at java.net.ServerSocket.bind(Unknown Source)
            at java.net.ServerSocket.<init>(Unknown Source)
            at java.net.ServerSocket.<init>(Unknown Source)
            at PortTest.main(PortTest.java:10)
4

2 に答える 2