本文介绍 PortSharing 示例。
TCP/IP 协议使用 16 位数字(称为端口)来区分与同一台计算机上运行的多个网络应用程序的连接。 如果应用程序正在侦听端口,则该端口的所有 TCP 流量将发送到该应用程序。 其他应用程序不能同时侦听该端口。
许多协议具有使用的标准或默认端口号。 例如,HTTP 协议通常使用 TCP 端口 80。 Internet Information Services (IIS) 具有一个侦听器,可在多个 HTTP 应用程序之间共享端口。 IIS 直接侦听端口,并根据消息流中的信息将消息转发到相应的应用程序。 这样,多个 HTTP 应用程序就可以使用相同的端口号,而无需争用端口来接收消息。
NetTcp 端口共享是 Windows Communication Foundation (WCF)功能,同样允许多个网络应用程序共享单个端口。 NetTcp 端口共享服务使用 net.tcp 协议接受连接,并根据消息的目标地址转发消息。
默认情况下未启用 NetTcp 端口共享服务。 运行此示例之前,必须手动启用该服务。 有关详细信息,请参阅 如何:启用 Net.TCP 端口共享服务。 如果服务已禁用,则启动服务器应用程序时会引发异常。
Unhandled Exception: System.ServiceModel.CommunicationException: The TransportManager failed to listen on the supplied URI using the NetTcpPortSharing service: failed to start the service because it is disabled. An administrator can enable it by running 'sc.exe config NetTcpPortSharing start= demand'.. ---> System.InvalidOperationException: Cannot start service NetTcpPortSharing on computer '.'. ---> System.ComponentModel.Win32Exception: The service cannot be started, either because it is disabled or because it has no enabled devices associated with it
在服务器上启用端口共享的方法是设置 PortSharingEnabled 绑定或 NetTcpBinding 绑定元素的 TcpTransportBindingElement 属性。 客户端不必知道如何配置端口共享以在服务器上使用它。
启用端口共享
以下代码演示如何在服务器上启用端口共享。 它使用随机 URI 路径在固定端口上启动服务实例 ICalculator
。 尽管两个服务可以共享同一端口,但它们的总体终结点地址仍必须是唯一的,以便 NetTcp 端口共享服务可以将消息路由到正确的应用程序。
// Configure a binding with TCP port sharing enabled
NetTcpBinding binding = new NetTcpBinding();
binding.PortSharingEnabled = true;
// Start a service on a fixed TCP port
ServiceHost host = new ServiceHost(typeof(CalculatorService));
ushort salt = (ushort)new Random().Next();
string address = $"net.tcp://localhost:9000/calculator/{salt}";
host.AddServiceEndpoint(typeof(ICalculator), binding, address);
host.Open();
启用端口共享后,可以多次运行服务,而不会与端口号发生冲突。 如果更改代码以禁用端口共享,启动两个服务副本会导致第二个副本失败并出现错误 AddressAlreadyInUseException。
Unhandled Exception: System.ServiceModel.AddressAlreadyInUseException: There is already a listener on IP endpoint 0.0.0.0:9000. 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. ---> System.Net.Sockets.SocketException: Only one usage of each socket address (protocol/network address/port) is normally permitted
运行示例
可以使用测试客户端检查消息是否已正确路由到共享端口的服务。
class client
{
static void Main(string[] args)
{
Console.Write("Enter the service number to test: ");
ushort salt = ushort.Parse(Console.ReadLine());
string address = $"net.tcp://localhost:9000/calculator/{salt}";
ChannelFactory<ICalculator> factory = new ChannelFactory<ICalculator>(new NetTcpBinding());
ICalculator proxy = factory.CreateChannel(new EndpointAddress(address));
// Call the Add service operation.
double value1 = 100.00D;
double value2 = 15.99D;
double result = proxy.Add(value1, value2);
Console.WriteLine("Add({0},{1}) = {2}", value1, value2, result);
// Call the Subtract service operation.
value1 = 145.00D;
value2 = 76.54D;
result = proxy.Subtract(value1, value2);
Console.WriteLine("Subtract({0},{1}) = {2}", value1, value2, result);
// Call the Multiply service operation.
value1 = 9.00D;
value2 = 81.25D;
result = proxy.Multiply(value1, value2);
Console.WriteLine("Multiply({0},{1}) = {2}", value1, value2, result);
// Call the Divide service operation.
value1 = 22.00D;
value2 = 7.00D;
result = proxy.Divide(value1, value2);
Console.WriteLine("Divide({0},{1}) = {2}", value1, value2, result);
Console.WriteLine();
Console.WriteLine("Press <ENTER> to terminate client.");
Console.ReadLine();
factory.Close();
}
}
服务的每个实例输出其唯一号码和地址。 例如,运行 service.exe时,可能会看到以下文本。
Service #4381 listening on net.tcp://localhost:9000/calculator/4381.
Press <ENTER> to terminate service.
输入运行 client.exe时在此处看到的服务编号。
Enter the service number to test: 4381
Add(100,15.99) = 115.99
Subtract(145,76.54) = 68.46
Multiply(9,81.25) = 731.25
Divide(22,7) = 3.14285714285714
Press <ENTER> to terminate client.
可以通过更改客户端使用的生成的地址,在跨计算机配置中运行此示例。 在Client.cs中,更改终结点地址格式字符串以匹配服务的新地址。 将对“localhost”的任何引用替换为服务器计算机的 IP 地址。 进行此更改后,必须重新编译示例。
设置、生成和运行示例
使用以下命令安装 ASP.NET 4.0。
%windir%\Microsoft.NET\Framework\v4.0.XXXXX\aspnet_regiis.exe /i /enable
确保已为 Windows Communication Foundation 示例 执行One-Time 安装过程。
如前一部分所述启用 NetTcp 端口共享服务。
若要生成解决方案的 C# 或 Visual Basic .NET 版本,请按照 生成 Windows Communication Foundation 示例中的说明进行操作。
若要在单台计算机或跨计算机配置中运行示例,请按照 运行 Windows Communication Foundation 示例中的说明进行操作。 运行此示例的特定详细信息之前包含在“运行示例”部分中。