Why do I have forbidden sockets?

I was tinkering with some C# code that uses TcpListeners recently, and hit on a strange issue where my code would run fine on on machine, and fail on another. It took me a while to find an answer in Google, so here’s a reminder to my future self:

Hey reader!
After many years, I’ve finally decided to start moving off WordPress and onto a blog I host myself. This post is now available at “https://blog.jermdavis.dev/posts/2021/why-do-i-have-forbidden-sockets“. Eventually this version will be retired so please update links on any sites you control, to avoid 404s in the future.

The initial issue

In amongst the code I was running was a fragment like this:

_listener = new TcpListener(IPAddress.Loopback, 1234);
_listener.Start();

On my home laptop this ran fine, but on another computer it crashed with an unexpected exception:

For Google’s benefit, the stack trace was:

Unhandled exception. System.Net.Sockets.SocketException (10013): An attempt was made to access a socket in a way forbidden by its access permissions.
   at System.Net.Sockets.Socket.UpdateStatusAfterSocketErrorAndThrowException(SocketError error, String callerName)
   at System.Net.Sockets.Socket.DoBind(EndPoint endPointSnapshot, SocketAddress socketAddress)
   at System.Net.Sockets.Socket.Bind(EndPoint localEP)
   at System.Net.Sockets.TcpListener.Start(Int32 backlog)
   at System.Net.Sockets.TcpListener.Start()
   at Channels.ConnectionListener.Start() in C:\Users\JDavis\Source\Repos\ChannelsExperiment\Channels\ConnectionListener.cs:line 24
   at Channels.Wrapper.Start() in C:\Users\JDavis\Source\Repos\ChannelsExperiment\Channels\Wrapper.cs:line 24
   at Channels.Program.Main(String[] args) in C:\Users\JDavis\Source\Repos\ChannelsExperiment\Channels\Program.cs:line 23
   at Channels.Program.<Main>(String[] args)

My initial thought was “ah, there’ll be something else using that port…” but running “netstat -ano” didn’t show a hit against the loopback address I was trying to bind:

Active Connections
  Proto  Local Address          Foreign Address        State           PID
  TCP    127.0.0.1:1029         127.0.0.1:1030         ESTABLISHED     5604
  TCP    127.0.0.1:1030         127.0.0.1:1029         ESTABLISHED     5604
  TCP    127.0.0.1:1715         127.0.0.1:1716         ESTABLISHED     5604
  TCP    127.0.0.1:1716         127.0.0.1:1715         ESTABLISHED     5604
  TCP    127.0.0.1:1763         127.0.0.1:62522        ESTABLISHED     10852
  TCP    127.0.0.1:62522        127.0.0.1:1763         ESTABLISHED     4780

(I checked against the real IP address of the machine as well – nothing there either)

So I fell back on “it was a security error – maybe I have fewer rights on this machine?” and tried running Visual Studio (and also my test app) as admin. But no difference there either.

The answer…

After a pile of futher googling I hit upon an idea that was entirely new to me. It turns out code can reserve a port, without ever actually opening it. That means Windows will refuse you rights to use it for anything else – but it won’t show up on the netstat call shown above. And the refusal comes up as the odd security error above.

To work this out you need a different command: “netsh interface ipv4 show excludedportrange protocol=tcp” and for me that gives:

Protocol tcp Port Exclusion Ranges

Start Port    End Port
----------    --------
      1132        1231
      1232        1331
      1435        1534
      1555        1654
      1819        1918
     50000       50059     *

* - Administered port exclusions.

My code tried to open port 1234, and that is included in the second of these ranges… Bingo!

The critical info here came from this Stack Overflow answer, if you want to read the original source.

So I can use this info to pick a port that’s free on all my machines, and my little bit of test code can run happily.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.