如何在C#中的随机端口上创建HttpListener类?

27 c# embeddedwebserver httplistener

我想创建一个在内部提供网页的应用程序,并且可以在同一台机器上的多个实例中运行.为此,我想创建一个HttpListener侦听端口的方法:

  1. 随机选择
  2. 目前尚未使用

基本上,我想要的是:

mListener = new HttpListener();
mListener.Prefixes.Add("http://*:0/");
mListener.Start();
selectedPort = mListener.Port;
Run Code Online (Sandbox Code Playgroud)

我怎么能做到这一点?

Ric*_*all 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;
}
Run Code Online (Sandbox Code Playgroud)

  • 这不回答有关HttpListener类的问题. (5认同)
  • 除了在方法结束时释放端口和启动HttpListener之间的竞争条件之外,我会说得足够公平. (5认同)
  • 只是为了您的信息,Google会在您的所有OAuth代码和示例中使用您的代码:) https://github.com/googlesamples/oauth-apps-for-windows/blob/a9c06c539adc21eab752537b234219c448356001/OAuthDesktopApp/OAuthDesktopApp/MainWindow.xaml.cs# L47) (3认同)
  • 不,没有办法知道这一点. (2认同)
  • 竞争条件使这个选项对我来说无法使用。间歇性错误太多。 (2认同)

小智 15

这样的事情怎么样:

    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;
    }
Run Code Online (Sandbox Code Playgroud)

我不确定你将如何找到该机器上正在使用的所有端口,但如果你试图监听已经使用的端口,你应该得到一个例外,在这种情况下,该方法只会选择另一个港口.

  • 您可能需要考虑使用`MinPort` /`MaxPort`常量,[MSDN link](http://msdn.microsoft.com/en-us/library/vstudio/system.net.ipendpoint_fields(v = vs. 110)的.aspx) (2认同)

Dre*_*kes 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;
}
Run Code Online (Sandbox Code Playgroud)

在我的机器上,此方法平均需要 15 毫秒,这对我的用例来说是可以接受的。希望这对其他人有帮助。