WCF (formerly Indigo), is the next generation way of developing distributed applications in .NET. Apart from being developed from Service Orientation perspective in mind and unifying all the distributed technologies of the Microsoft stack, it encompasses a variety of other features which either might not be highlighted or might be not been well documented. One among those features is the port sharing feature on TCP protocols. Organizations have NAT and firewalls for obvious security reasons. If any application that needs to be deployed and accessed across the firewall, one needs to rely on the common TCP ports that firewalls open. HTTP protocol normally uses Port 80. Thanks to the usage of HTTP.sys and IIS 6.0, wherein Port 80 can be used and shared across multiple applications, the problem is that there is not a single way in which we can enable port sharing via TCP.
What if the same port can be shared across multiple applications that run on TCP?
The answer to the same lies in the
NET.TCP Port Sharing feature of WCF. In this article, we will see how easily we can achieve the same in WCF.
What happens if same port is been used by applications running on TCP ?
In the above application, App 1 is running on TCP Port 2555 and client 1 is interacting with it. Now if Client 2 wants to access App 2 on the same port 2555, it will encounter the following error:
"There is already a listener on IP endpoint <Endpoint ID>. Make sure that you are not trying to use this endpoint multiple times in your application and that there are no other applications listening on this endpoint. "
NET.TCP Port sharing
NET.TCP Port sharing service, multiple applications in WCF can share the same ports.
Look at the above diagram, the logic lies in the Windows service that ships with WCF called NET.TCP Port Sharing Service which enables multiple port sharing through WCF.
Sharing a common port on TCP is a three step process in WCF:
- Enable the
NET.TCP Port Sharing Service(disabled by default)
- Use TCP protocols in WCF Services
- Setting the
PortSharingEnabled Property to
We will look at each of these steps one by one.
Step 1. Enabling NET.TCP Port Sharing Service
Installing .NET 3.0 installs a suite of other services. One of the Window services that gets installed is
NET.TCP Port Sharing Service. This service enables WCF services, running on the different process, sharing the same port. The advantage of the same is that multiple applications running on TCP no longer need to open a separate port for each of them. This service is been hosted by a process called SMSvcHost.exe that resides in "c:\WINDOWS\Microsoft.NET\Framework\v3.0\Windows Communication Foundation" folder(Replace C with your Windows root directory). Internally, this process manages the TCP socket for the services that have port sharing enabled (specified in Step 3). By default, this service is disabled and needs to be started. To enable it:
- Open Run and type
services.msc. Click on OK
NET.TCP Port Sharing Service in the Name column from the service Management Console
- Start the service
Step 2. use TCP protocols in WCF Services
WCF services can be consumed only via its endpoints. Endpoints are the entry point for the service. .NET compiler will give a compile time error if WCF services do not have any endpoints. Endpoints consist of Address, Binding and Contract. Bindings in WCF determine how to consume any WCF service. They contain the information about the protocol being used, transaction requirements, security requirements, type of communication etc. to name a few. Microsoft has come up with pre-defined bindings and most of the time, your requirements can get fulfilled with these predefined bindings. In case none of the predefined bindings fulfills your requirement, you can also create your custom bindings. These bindings can be specified either through imperative code or through a configuration file. Few of these predefined bindings use TCP protocol like
NetPeerTcpBinding. For using multiple ports sharing via
Net.TCP port sharing service, create an endpoint and use one of the above TCP Binding.
To know about how to create endpoints, read this.
Step 3 : Setting the PortSharingEnabled Property to true
<binding name="PortBinding" portSharingEnabled="true" />
The above code is an excerpt from the configuration file. This task can be done through the imperative code by instantiating
NetTcpBinding and setting its
NetTcpBinding binding = new NetTcpBinding();
binding.PortSharingEnabled = true;
Step 3 is delegating the task of monitoring the TCP port to SMSvcHost.exe for all the services using the above binding and enables port sharing. It will thereby, monitor all the TCP traffic on that server, and route it to the destined address of an application. So when any WCF service running on TCP protocol and using the
PortBinding comes up, the WCF engine does not open the port directly, instead it delegates this responsibility to
NET.TCP Port sharing service, which not only opens a port for that service but also acts as a listener of that port. There is no tweak of settings involved on the client side.
SMSvcHost.exe also contains the configuration file called SMSvcHost.exe.config residing in the same root directory. This configuration file manages the list of all those processes that might use the port sharing feature and list of USER accounts that can run this Windows Service. Each of the services running on different processes should have a different URI though they share the same port. This service can only be used over the TCP protocol and can't be used on top of HTTP or Named Pipes. However, it too opens the doors of opportunities for product development and sigh of relief to system administrators. They no longer need to compromise with the security of firewalls.