次の方法で共有


Net.TCP ポート共有のサンプル

この記事では、PortSharing サンプルについて説明します。

TCP/IP プロトコルでは、ポートと呼ばれる 16 ビット番号を使用して、同じコンピューター上で実行されている複数のネットワーク アプリケーションへの接続を区別します。 アプリケーションがポートをリッスンしている場合、そのポートのすべての TCP トラフィックがそのアプリケーションに送信されます。 他のアプリケーションでは、そのポートを同時にリッスンできません。

多くのプロトコルには、使用する標準または既定のポート番号があります。 たとえば、HTTP プロトコルでは通常、TCP ポート 80 が使用されます。 インターネット インフォメーション サービス (IIS) には、複数の HTTP アプリケーション間でポートを共有するリスナーがあります。 IIS はポートを直接リッスンし、メッセージ ストリーム内の情報に基づいて適切なアプリケーションにメッセージを転送します。 これにより、複数の HTTP アプリケーションで、メッセージを受信するためにポートを予約するために競合することなく、同じポート番号を使用できます。

NetTcp ポート共有は、複数のネットワーク アプリケーションが 1 つのポートを共有できるようにする 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

NetTcpBinding バインディングまたは TcpTransportBindingElement バインド要素のPortSharingEnabled プロパティを設定することで、サーバーでポート共有が有効になります。 クライアントは、サーバーでポート共有を使用するように構成されている方法を知る必要はありません。

ポート共有の有効化

次のコードは、サーバーでポート共有を有効にする方法を示しています。 ランダムな URI パスを使用して、固定ポートで ICalculator サービスのインスタンスを開始します。 2 つのサービスが同じポートを共有できる場合でも、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();

ポート共有を有効にすると、ポート番号を競合させることなく、サービスを複数回実行できます。 ポート共有を無効にするようにコードを変更した場合、サービスの 2 つのコピーを起動すると、2 つ目が 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 アドレスに置き換えます。 この変更を行った後、サンプルを再コンパイルする必要があります。

サンプルを設定、ビルド、実行するには

  1. 次のコマンド ASP.NET 使用して 4.0 をインストールします。

    %windir%\Microsoft.NET\Framework\v4.0.XXXXX\aspnet_regiis.exe /i /enable
    
  2. Windows Communication Foundation サンプル One-Time セットアップ手順を実行していることを確認します。

  3. 概要セクションで前述したように、NetTcp ポート共有サービスを有効にします。

  4. ソリューションの C# または Visual Basic .NET エディションをビルドするには、「Windows Communication Foundation サンプルのビルド」の手順に従います。

  5. 単一または複数のコンピューター間の構成でサンプルを実行するには、「Windows Communication Foundation Samplesの実行」の手順に従います。 このサンプルを実行するための具体的な詳細については、「サンプルの実行」セクションを参照してください。