title: Is listening on ports slower in Windows than in Linux?
body: <p>I wrote a simple program that makes a port range open by listening on the ports specified. I noticed, that it takes different time on Windows and on Linux for this program to open all ports from port 1 to port 65535.</p>
  
  <p>On Linux it takes about 2 seconds opening all of the ports. On Windows it's closer to half an hour (I  did not measure the exact number of minutes, because I never waited for it to finish).</p>
  
  <p><strong>Is Windows objectively slower in this regard, and if yes, why and can I do anything to make this run faster?</strong></p>
  
  <p>Note, that while tests were run on very different hardware, it probably does not matter, given that the timing differs in orders of magnitude.</p>
  
  <pre><code>// 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 &lt;= endPort; i++)
              {
                  if (i % 100 == 0 &amp;&amp; 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);
          }
      }
  }
  </code></pre>
  
  <p><strong>Update 1</strong>, so this is apparently has nothing to do with .net as such. If we capture a diagnostic trace as described <a href="https://blogs.msdn.microsoft.com/canberrapfe/2012/03/30/capture-a-network-trace-without-installing-anything-capture-a-network-trace-of-a-reboot/" rel="nofollow noreferrer">here</a> or <a href="http://blogs.technet.com/b/nettracer/archive/2010/10/06/how-it-works-under-the-hood-a-closer-look-at-tcpip-and-winsock-etl-tracing-on-windows-7-and-windows-2008-r2-with-an-example.aspx" rel="nofollow noreferrer">here</a>, we will see something like this:</p>
  
  <p><a href="https://i.stack.imgur.com/3hcNn.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/3hcNn.png" alt="enter image description here"></a></p>
  
  <p>This tells us that winsock <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/ms739168(v=vs.85).aspx" rel="nofollow noreferrer">listen</a> call takes in vicinity of 400 milliseconds. Any idea why?</p>
  
  <p><a href="https://stackoverflow.com/questions/14249739/tcplistener-performance-issues-with-start-after-hundreds-of-ports-open">This question</a> describes similar problem, and some people can reproduce that and some cannot. My guess would be that it depends on Windows/SP version. I'm running <strong>Windows 10</strong>. Long time ago, there was a rate limiting issue for half-open connection, which caused many people grief, because they could not run their torrents as efficiently. This might be caused by something similar, although it does not look like this is related to that old issue.</p>
  
  <p><strong>Update 2</strong> - tested on Windows 7 machine, and it worked very fast (comparable to linux timings). Apparently something changed since then?</p>