在Windows系统和Linux系统中,监听端口的速度哪个更慢?

3
我写了一个简单的程序,通过监听指定端口使端口范围开放。我发现,在Windows和Linux上,这个程序打开从端口1到65535的所有端口所需的时间不同。
在Linux上,打开所有端口大约需要2秒钟。在Windows上,这个过程接近半个小时(我没有测量确切的分钟数,因为我从来没有等待它完成)。
Windows在这方面是否明显较慢,如果是,原因是什么,我能做些什么来加快运行速度吗?
请注意,尽管测试运行在非常不同的硬件上,但鉴于计时的数量级差异,这可能并不重要。
// This is a very basic TCP port listener that allows you to listen on a port range
// If you run this program outside of firewall and run a port scanner inside a firewall
// pointing to the ip address where this program runs, the port scanner will be able you
// to tell which exactly ports are open on the firewall
// This code will run on Windows, but most importantly also on linux.
// DigitalOcean.com has all ports for their VMs open by default. So spin a new VM,
// copy pln.cs in your (root) home folder and then run:
// sudo apt-get update
// sudo apt-get install mono-complete -y
// mcs pln.cs
// ulimit -n 66000
// ./pln.exe 1 65535
// Now you can use the VM ip address to determine open ports on your firewall
// Note that this is a dev utility, and is aimed to be minimal - no input validation,
// no error handling. In case of a error stack trace is dumpled to console

using System;
using System.Net;
using System.Net.Sockets;

namespace PortListener
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                Console.WriteLine("Usage: pln.exe startPort [endPort]");
                Listen(args);
            }
            catch (Exception ex)
            {
                Console.WriteLine("Error: " + ex);
            }
        }

        private static void Listen(string[] args)
        {
            int startPort = int.Parse(args[0]);
            int endPort = int.Parse(args[1]);
            Console.WriteLine("Started binding...");
            for (int i = startPort; i <= endPort; i++)
            {
                if (i % 100 == 0 && Environment.OSVersion.Platform != PlatformID.Unix)
                {                    
                    Console.WriteLine("Binding port " + i);
                }
                TcpListener listener = new TcpListener(IPAddress.Any, i);
                try
                {
                    listener.Start();
                }
                catch (SocketException ex)
                {
                    if (ex.SocketErrorCode == SocketError.AddressAlreadyInUse)
                    {
                        Console.WriteLine("Port " + i.ToString() + " already in use");
                        continue;
                    }
                    if (ex.SocketErrorCode == SocketError.AccessDenied)
                    {
                        Console.WriteLine("Access denied to port " + i.ToString());
                        continue;
                    }
                    throw;
                }
                listener.BeginAcceptSocket(DoAcceptSocketCallback, listener);
            }
            Console.WriteLine("Finished binding. Ctrl-C to stop.");
            Console.ReadLine();

        }
        private static void DoAcceptSocketCallback(IAsyncResult ar)
        {
            TcpListener listener = (TcpListener) ar.AsyncState;
            listener.EndAcceptSocket(ar).Close();
            Console.WriteLine("Connection on port " + ((IPEndPoint) listener.LocalEndpoint).Port.ToString());
            listener.BeginAcceptSocket(DoAcceptSocketCallback, listener);
        }
    }
}

更新1,所以这显然与.net无关。如果我们按照此处此处所述的方法捕获诊断跟踪,我们将看到如下内容:

enter image description here

这告诉我们winsock listen调用需要大约400毫秒的时间。有什么想法吗?

这个问题描述了类似的问题,有些人可以重现,而有些人则不能。我猜测这可能取决于Windows/SP版本。我正在运行Windows 10。很久以前,半开放连接存在速率限制问题,这给许多人带来了烦恼,因为他们无法有效地运行他们的torrent。尽管它看起来与旧问题无关,但这可能是由类似的原因引起的。

更新2 - 在Windows 7机器上测试,速度非常快(与Linux时间相当)。显然从那时起有些变化?


@OscarVicentePerez,大部分时间都花在了listener.Start();上。这告诉你什么? - Andrew Savinykh
你不是唯一遇到这个问题的人。请查看http://stackoverflow.com/questions/14249739/tcplistener-performance-issues-with-start-after-hundreds-of-ports-open并搜索相关信息。或许可以尝试使用另一个 .Net 目标。 - Oscar Vicente Perez
@OscarVicentePerez,是的,我已经看到了。而且它似乎与.net目标没有任何关系。(请参见更新)。神秘!我认为观察到这一点和没有观察到这一点之间的区别在于他们的操作系统版本——只是一个猜测。 - Andrew Savinykh
启动函数在应用程序启动时被调用(用于绑定套接字)。为什么它的速度很重要呢?它只是接受套接字,这应该是快速的,对吧? - jgauffin
@jgauffin,完全正确。仍然在想为什么。Linux没有这个问题,某些Windows安装也没有。一定有原因。 - Andrew Savinykh
显示剩余4条评论
1个回答

1

所以,是的。糟糕的驱动器。

没有延迟的计算机和有大延迟的计算机之间的区别在于,没有延迟的计算机没有安装很多垃圾软件。

下载一个工具,可以查看已安装的驱动程序,并尝试猜测哪些驱动程序会导致减速。您可以使用Sysinternals套件中的Autoruns(参见驱动程序选项卡)或Nirsofts DriverViewInstalledDriversList

如果您使用后者,请按组列排序驱动程序列表,并查看NDIS和/或网络。最有可能是其中之一。

因此,当我开始时,我测量了在我的计算机上打开端口1到10000需要多长时间。然后我逐个删除驱动程序并再次进行测量。结果如下:

All Crap installed                                   - 226 seconds
Same as above but removed Networx Traffic monitor    -   9 seconds
Same as above but removed TeamViewer remote assistance - 7 seconds
Same as above but removed Checkpoint VPN client        - 0 seconds

注意,仅关闭这些程序是无效的。需要删除/禁用驱动程序才能看到改进。
所以不要责怪Windows。还有很多其他软件供应商可供选择 ;)

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