How to use reserved port in netTcpBinding and basicHttpBinding in a WCF Application
One of my colleagues was working with a customer where they were using a self-hosted WCF service with basicHttpBinding.
Basically the customer wanted to use around 20 ports of his choice so that, they can distribute different service URL to different dealers, that's cool stuff, right there.
However there are some issues to consider, in fact, initially ports were getting consumed by different applications in random manner so that was a problem that needed to be adressed.
After some thought about it they came up with the resolution to reserve ports using below command:
netsh int ipv4 add excludedportrange protocol=tcp startport=57069 numberofports=20
Seems ok, right? Not...
After reserving the ports, they started getting below error from WCF application however they were able to consume same port from Powershell command:
System.ServiceModel.AddressAlreadyInUseException: HTTP could not register URL http://+:57069/ because TCP port 57086 is being used by another application. ---> System.Net.HttpListenerException: The process cannot access the file because it is being used by another processat System.Net.HttpListener.AddAllPrefixes()at System.Net.HttpListener.Start()at System.ServiceModel.Channels.SharedHttpTransportManager.OnOpen()
To provide some context, below where their working Powershell command
$listener = [system.net.sockets.tcplistener]57069 $listener.Start()
Based on the above lets start discussing the troubleshoot done.
First we tried to isolate the failure, and for that we used Powershell :-) .
The initial step was trying to reproduce the issue that we were seeing on the WCF Application using Powershell only.
And we found out that if we used below commands, we will get the same error as we got from the WCF application.
netsh int ipv4 add excludedportrange protocol=tcp startport=57069 numberofports=1 PS C:\Windows\system32> $httpPrefixUri = New-Object System.Uri("http://localhost:57069/CalculatorService/") PS C:\Windows\system32> $httpListener = New-Object System.Net.HttpListener PS C:\Windows\system32> $httpListener.Prefixes.Add($httpPrefixUri) PS C:\Windows\system32> $httpListener.Start()
And below was the error:
Exception calling "Start" with "0" argument(s): "The process cannot access the file because it is being used by another process" At line:1 char:1 + $httpListener.Start()
In the Event Viewer we were seeing the following error:
Log Name: System
Date: 4/17/2018 5:37:32 PM
Event ID: 15005
Task Category: None
Unable to bind to the underlying transport for [::]:57069. The IP Listen-Only list may contain a reference to an interface which may not exist on this machine. The data field contains the error number.
Looking at this information with some attention we clearly understand that the issue is being caused by the fact this "Listen-Only" list wasn't present in the system.
So, obvious solution would be adding it for all addresses that we wanted to use, that will solve our issue.
Steps to Resolve
We had ran below Powershell command:
PS C:\Windows\system32> netsh http add iplisten 0.0.0.0 IP address successfully added
The above command adds registry subkey as below:
Note: Adds a new IP address to the IP listen list. This does not include the port number. The IP listen list is used to scope the list of addresses to which the HTTP service binds. "0.0.0.0" means any IPv4 address and "::" means any IPv6 address.
After implementing the fix, we tested again using below Powershell command:
PS C:\Windows\system32> $httpListener = New-Object System.Net.HttpListener PS C:\Windows\system32> $httpListener.Prefixes.Add($httpPrefixUri) PS C:\Windows\system32> $httpListener.Start() PS C:\Windows\system32> netstat -ano | select-string -Pattern 57069
And voila, problem solved..
TCP 0.0.0.0:57069 0.0.0.0:0 LISTENING 4