Resolving conflict: Http ports and XPSP2
A giant leap forward in Windows HTTP technologies was introduced with Windows Server 2003, namely http.sys. Http.sys includes a kernel-mode listener that can dispatch to any process on the machine. This was great news to those of us that wanted to share port 80 with other applications (IIS for example). It also has a comprehensive namespace security mechanism which admins can use to delegate sections of the global hierarchical directory space to less-privileged accounts. IIS 6.0 (which shipped with Server 2003) was built on top of http.sys and so did not require exclusive access to its configured port #s.
Indigo’s standalone HTTP IChannelListeners are built on top of http.sys. That means that if you are not hosted in IIS, your process will need to have access to any http addresses that your ServiceHost is configured with. If the process is not running as admin you will need to add a reservation using httpcfg.exe. Alternatively, you can call the HTTP configuration APIs, such as HttpSetServiceConfiguration, directly.
There is one more wrinkle when working on XPSP2. While http.sys was backported to XP as part of Service Pack 2 (yay), IIS 6.0 was not (boo). This means that if you have IIS running on your XP box, then you are using IIS 5.1 which is built on top of a listening socket and thus owns port 80. If you try to open a Service using port 80 while IIS is running you will get the following error:
AddressAlreadyInUseException: HTTP could not register URL http://+:80/myService/ because TCP port 80 is being used by another application.
You have 2 choices to remedy this situation:
- Stop IIS (using “net stop w3svc”)
- Setup your service to use a different port#
Setting up a different port# is usually a simple matter of changing your Service’s URL. However, a more subtle variation of this failure occurs for clients that use WsDualHttpBinding (or a custom binding with CompositeDuplexBindingElement and HttpTransportBindingElement). Your indication here is the inclusion of “Temporary_Indigo_Addresses” as in:
AddressAlreadyInUseException: HTTP could not register URL http://+:80/Temporary_Listen_Addresses/51E705D5-E7B5-472B-B6B9-A6A60FE93B7A/ because TCP port 80 is being used by another application.
When your client is using a Dual binding, then the system creates a temporary address to listen on, in order to establish two-way communication over two one-way channels. For HTTP, this address by default is setup on a subtree of http://+:80/Temporary_Indigo_Addresses. This has the advantage of being a namespace pre-ACLed by Indigo for access by all processes. You can override this default through the ClientBaseAddress property on WsDualHttpBinding and CompositeDuplexBindingElement. You can do this either through code:
binding.ClientBaseAddress = "http://localhost:8000/myClient/"
or config:
<wsDualHttpBinding clientBaseAddress="http://localhost:8000/myClient/"/>
Good luck on future port conflict avoidance!
July 28th, 2006 at 7:59 am
Hi I had the
AddressAlreadyInUseException: HTTP could not register URL http://+:80/Temporary_Listen_Addresses/51E705D5-E7B5-472B-B6B9-A6A60FE93B7A/ because TCP port 80 is being used by another application.
Problem and Your solution guded me the right way. However there is one little problem on your suggested solution.
when the clientBaseAddress is specifyed the address should directly refer to the client Machine menaing can not be stated as localhost or the connection will time out.
E.x.
you set cant clientBaseAddress=http://localhost:8000/client/,
it Should be http://clientmachinename:8000/client
Thank you again for the Help
August 11th, 2006 at 12:16 pm
Yes, localhost was used as an example for when you are accessing a service on the same machine. if you are doing cross-machine communication then you need to use a resolvable address (i.e. your client machine name for example)
September 1st, 2006 at 7:30 am
But when you are distributing your application, you obviously do not know the clientmachinenames, so you will have to do this in code. Bummer
October 6th, 2006 at 12:02 pm
You can have your deployment app (which installs/generates the client configuration file) detect the client machine name, yes?
November 13th, 2006 at 8:40 am
Excellent information, Kenny. Thanks a ton.
November 30th, 2006 at 10:03 am
Thanks Kenny - that helped out greatly.
A couple of additional notes, related to my experience.
1) I found that, if the service is already using a non-standard port, the client should use a different non-standard port (e.g. Service uses port 666, Client uses port 667). This may be obvious to some.
2) Anti Virus programs may complain if non-standard ports are used. Mine did, so I had to add the two applications to the permitted list of executable files.
May 15th, 2007 at 12:16 pm
Does this mean that i could have a self hosted WCF service share port 80 with IIS? If so, how do i go about sharing the port?
June 13th, 2007 at 6:25 am
Really good help Kenny but i have one problem
I have override ClientBaseAddress property on WsDualHttpBinding like
clientBaseAddress=”http://localhost:1045/WCFTest.Host/”>
Now it gives me this error:
HTTP could not register URL http:// :1045/WCFTest.Host/ because TCP port 1045 is being used by another application
what should i do? please help me.
***********This is my configuration code **************************
June 13th, 2007 at 9:47 am
Darshan, you can share port 80 with IIS if you are using 2k3 server or later (that is, IIS 6.0 and later). IIS 5.1 (on XP) does not use http.sys and there for you cannot share port 80 with IIS on XP.
Sunil, it sounds like an application already has 1045 open. You can use “netstat -a” to see which process has 1045 in LISTENING mode.
July 19th, 2007 at 2:44 am
Thanks a lot!
December 28th, 2007 at 4:55 pm
when You say that we have to “use resolvable address (i.e. your client machine name for example)”
You mean that client computer has to be ‘visible’ from server?
by ‘visible’ I mean that you can ping client computer from server by it’s name
in my app.config I have clientBaseAddress=”http://client_machine_name:8000/myClient/”
but I still get timeouts…
please help…
January 19th, 2008 at 12:05 pm
This is great, but how do I detect the client’s machine name from .NET? And there is one more thing: if I specify a clientBaseAddress and run more than one instances of the client application, it will also throw this exception, because the other instance of the client already uses that particular port.
August 14th, 2008 at 12:11 pm
I am just now delving into WCF and I am trying to reolve the latter error you described for IIS 5.1 running on XP. I have attempted to emulate your solution but I still get the same error - below is my configuration file - can you please help? Thanks!
August 14th, 2008 at 12:55 pm
I have a Windows 2003 Server and I deployed the service to that server such that the reference is now 10.10.90.1 instead of localhost. I also chnaged the clientBaseAddress to http://10.10.90.1:8000/StockService/ and I am still getting the same error - any ideas?
BTW - THe WSDL looks fine and I can obtain it without any problems through a browser.