32

Web ページを内部的に提供し、同じマシン上の複数のインスタンスで実行できるアプリケーションを作成したいと考えています。HttpListenerそのために、次のポートでリッスンする を作成したいと思います。

  1. ランダムに選択
  2. 現在未使用

基本的に、私が欲しいのは次のようなものです:

mListener = new HttpListener();
mListener.Prefixes.Add("http://*:0/");
mListener.Start();
selectedPort = mListener.Port;

どうすればこれを達成できますか?

4

7 に答える 7

41

ポート 0 にバインドしている場合、TcpListener はリッスンする未使用のポートをランダムに見つけます。

public static int GetRandomUnusedPort()
{
    var listener = new TcpListener(IPAddress.Any, 0);
    listener.Start();
    var port = ((IPEndPoint)listener.LocalEndpoint).Port;
    listener.Stop();
    return port;
}
于 2010-10-20T12:55:46.973 に答える
16

このようなものはどうですか:

    static List<int> usedPorts = new List<int>();
    static Random r = new Random();

    public HttpListener CreateNewListener()
    {
        HttpListener mListener;
        int newPort = -1;
        while (true)
        {
            mListener = new HttpListener();
            newPort = r.Next(49152, 65535); // IANA suggests the range 49152 to 65535 for dynamic or private ports.
            if (usedPorts.Contains(newPort))
            {
                continue;
            }
            mListener.Prefixes.Add(string.Format("http://*:{0}/", newPort));
            try
            {
                mListener.Start();
            }
            catch
            {
                continue;
            }
            usedPorts.Add(newPort);
            break;
        }

        return mListener;
    }

そのマシンで使用されているすべてのポートをどのように見つけるかはわかりませんが、既に使用されているポートをリッスンしようとすると例外が発生するはずです。その場合、メソッドは単に別のポートを選択しますポート。

于 2008-10-21T19:38:45.603 に答える
7

Snooganz's answerから派生した回答を次に示します。可用性のテストとその後のバインドの間の競合状態を回避します。

public static bool TryBindListenerOnFreePort(out HttpListener httpListener, out int port)
{
    // IANA suggested range for dynamic or private ports
    const int MinPort = 49215;
    const int MaxPort = 65535;

    for (port = MinPort; port < MaxPort; port++)
    {
        httpListener = new HttpListener();
        httpListener.Prefixes.Add($"http://localhost:{port}/");
        try
        {
            httpListener.Start();
            return true;
        }
        catch
        {
            // nothing to do here -- the listener disposes itself when Start throws
        }
    }

    port = 0;
    httpListener = null;
    return false;
}

私のマシンでは、この方法は平均で 15 ミリ秒かかりますが、これは私のユース ケースでは許容範囲です。これが他の誰かに役立つことを願っています。

于 2017-10-10T12:06:37.903 に答える
1

残念ながら、これは不可能です。Richard Dingwall が既に提案したように、TCP リスナーを作成してそのポートを使用できます。このアプローチには、次の 2 つの問題が考えられます。

  • 理論的には、別の TCP リスナーがこのポートを閉じた後にこのポートを使用する可能性があるため、競合状態が発生する可能性があります。
  • 管理者として実行していない場合は、プレフィックスとポートの組み合わせを割り当てて、バインドできるようにする必要があります。これは、管理者権限がないと管理できません。基本的に、これは HTTP サーバーを管理者特権で実行する必要があることを意味します (これは一般的に悪い考えです)。
于 2016-07-08T06:51:19.050 に答える
0

これが可能だとは思いません。UriBuilder.Port のドキュメントには、「ポートが URI の一部として指定されていない場合、... プロトコル スキームのデフォルトのポート値がホストへの接続に使用されます。」と記載されています。

https://msdn.microsoft.com/en-us/library/system.uribuilder.port(v=vs.110).aspxを参照してください。

于 2015-10-15T20:28:52.980 に答える