无法在Windows 10上监听特定端口

9
我发现我的Windows 10电脑上有一些端口既没有被进程使用,也无法监听。我发现这个问题是在尝试运行一个占用3000端口的节点服务器时发现的。我在这个主题上找到了许多相关问题,例如Node.js Port 3000 already in use but it actually isn't?。所有这些问题的回答者都建议使用"netstat -ano"查找使用该端口的进程并将其停止。但事实上,我发现有很多端口被阻止了,并未与进程绑定,这与杀毒软件和防火墙均无关,因为我关闭了防火墙,只开启了Windows Defender杀毒软件。我编写了一个程序来监听127.0.0.1上从3000到5000的所有端口。
        int port = 3000;
        while(port <= 5001)
        {
            try
            {
                ListenOnPort(port);
                ++port;

            }
            catch (Exception ex)
            {
                Console.WriteLine($"Listen on {port} failed: {ex.Message}");
                ++port;
            }
        }

Where ListenOnPort is...

    private static void ListenOnPort(int v)
    {
        var uri = new UriBuilder("http", "127.0.0.1", v);
        HttpListener listener = new HttpListener();
        listener.Prefixes.Add(uri.Uri.ToString());
        Console.WriteLine($"Listening on {v}");
        listener.TimeoutManager.IdleConnection = new TimeSpan(0, 0, 1);
        listener.Start();
        var task = listener.GetContextAsync();
        if(task.Wait(new TimeSpan(0,0,1)))
        {
            HttpListenerResponse response = task.Result.Response;
            // Construct a response.
            string responseString = "<HTML><BODY> Hello world!</BODY></HTML>";
            byte[] buffer = System.Text.Encoding.UTF8.GetBytes(responseString);
            // Get a response stream and write the response to it.
            response.ContentLength64 = buffer.Length;
            System.IO.Stream output = response.OutputStream;
            output.Write(buffer, 0, buffer.Length);
            // You must close the output stream.
            output.Close();
        }
        listener.Stop();
    }

该程序产生的输出类似于以下内容...
Listening on 3000
Listen on 3000 failed: The process cannot access the file because it is being used by another process
Listening on 3001
Listen on 3001 failed: The process cannot access the file because it is being used by another process
Listening on 3002
Listen on 3002 failed: The process cannot access the file because it is being used by another process
Listening on 3003
Listen on 3003 failed: The process cannot access the file because it is being used by another     process
Listening on 3004
Listen on 3004 failed: The process cannot access the file because it is being used by another process
Listening on 3005
Listen on 3005 failed: The process cannot access the file because it is being used by another process
Listening on 3006
Listening on 3007
Listening on 3008
Listening on 3009
Listening on 3010

我发现在3000至5000的范围内,有624个端口被阻止了。而“netstat -ano”显示该范围内只使用了5个端口。那么是什么阻止了剩下的619个端口呢?

哎呀,你本来可以把所有的东西都扔掉,然后用 socket()bind()close() 来替换它们。 - user207421
2个回答

13

没错...

在寻找其他东西的时候,我找到了答案(至少是问题的根源)。我无法连接到这些端口的原因是它们都是Windows上被排除的端口范围的一部分。要查看排除的端口,请使用...

$ netsh int ipv4 show excludedportrange tcp

神奇的是,那里列出了我无法连接的所有端口。这些被排除的端口范围显然来自于我已安装的HyperV和Docker。有一种方法可以恢复这些端口......但并不容易,因为它涉及卸载Docker和HyperV,然后保留端口范围,最后重新安装HyperV和Docker。这并不值得。现在我只要知道如何找到我不能使用的端口,那么我就会简单地不使用它们!


谢谢!我一直在想为什么我的一些Kubernetes端口转发在Windows 10浏览器中无法工作,但在WSL2内部可以工作。例如: Elasticsearch = 9200 Prometheus = 9090 Alertmanager = 9093 PushGateway = 9091 我成功地创建了一个端口转发,但在WSL2之外,Windows系统就是不监听这些端口。现在我知道原因了。 - Michael
谢谢!我遇到了同样的问题,我的Mariadb监听端口是3306。 - tommybee

3

将Windows的“动态端口范围”设置在非冲突的位置

如果您无法更改端口号(例如非可配置应用程序),我们成功地解决了此问题。

当您发出以下命令时:

netsh int ip show excludedportrange protocol=tcp

您将获得一个输出,其中包含一系列已保留的端口范围:

Protocol tcp Port Exclusion Ranges

Start Port    End Port
----------    --------
     33474       33573
     50000       50059     *
     58159       58258
     58259       58358
     58359       58458
     58459       58558
     58559       58658
     58659       58758
     58759       58858

* - Administered port exclusions.

最有可能的原因是Windows Hyper-V(Microsoft的硬件虚拟化产品)保留了随机端口范围(通常是100个端口的块)。这会成为一个烦恼,因为如果您正在开发使用多个端口的应用程序或较大的解决方案,在重新启动系统后有时会发生冲突,有时则不会
要查找“动态端口范围”,您可以输入以下命令:
netsh int ipv4 show dynamicport tcp

答案:
Protocol tcp Dynamic Port Range
---------------------------------
Start Port      : 1024
Number of Ports : 64511

您可以指示Windows将此范围修改为与冲突区域不同。假设您的开发在端口60000以下和以上,您可以发出以下命令来限制动态端口范围:(您必须拥有管理员权限)

netsh int ipv4 set dynamic tcp start=60001 num=5534

为了让Hyper-V(以及Windows系统)使用这个新的动态范围,您需要重新启动系统。

现在,如果我们请求排除的端口范围:

netsh int ip show excludedportrange protocol=tcp

响应已经发生变化:

Protocol tcp Port Exclusion Ranges

Start Port    End Port
----------    --------
     50000       50059     *
     63904       64003
     64004       64103
     64105       64204
     64205       64304
     64305       64404
     64405       64504
     64505       64604
     64605       64704

* - Administered port exclusions.

只有“管理的端口排除”位于60001以下。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接