0

私の目標は、受信ポートを開かずに、ファイアウォールの背後にある WCF サービスに到達することです。私が選択した解決策は、パブリック側で二重 WCF サービスをホストすることです。これは、ファイアウォールが関与していない場合に使用されたものと同じコントラクトをコールバックとして持ちます。

netTcpBinding を使用した場合は機能しましたが、ストリーミング通信が必要なため、カスタム バインディングを使用する必要がありました。

ファイアウォールを立ち上げるまで、すべてが正常に機能します。その時点で、(ファイアウォールの背後からの) 直接呼び出しは正常に機能しますが、コールバックは機能しません (ファイアウォールが停止します)。

質問はなぜですか?定義済みの netTcpBinding と同じチャネルを使用するべきではありませんか?

app.config のチャネル スタックは次のとおりです。

<customBinding>
  <binding name="ReversedServiceBinding">
    <compositeDuplex />
    <oneWay />
    <binaryMessageEncoding />
    <tcpTransport transferMode="Streamed" />
  </binding>
</customBinding>
4

1 に答える 1

2

実際の動作は正しいです。あなたはcompositeDuplexバインディング要素を使用しました - 複合語の意味はまさにあなたが得るものです - それぞれが一方向に働く2つの別々のチャンネルです。複合デュプレックスは、デフォルトでデュプレックス通信をサポートしていないトランスポート チャネルにのみ必要です。これは、TCP トランスポート チャネル チェックの注釈には当てはまりません。compositeDuplex を使用しない場合、期待どおりに動作するはずです。また、ストリーミング トランスポートを許可するためにまったく新しいカスタム バインディングを定義する必要もありません。NetTcpBindingには、構成で指定できる TransportMode プロパティもあります。

編集: Net.TCP 二重通信を使用した作業例を用意しました。ストリーミングは使用しません。二重化 TCP 通信を使用すると、ストリーミングができないというのは正しいです。二重通信とチャンク チャネルを組み合わせたり、WCF Xtensions (市販製品) を確認したりできます。

共有契約

namespace NetTcpDuplexContracts
{
    [ServiceContract(SessionMode = SessionMode.Required, 
        CallbackContract = typeof(IDuplexServiceCallback))]
    public interface IDuplexService
    {
        [OperationContract(IsOneWay = true)]
        void DoAction(string message);
    }

    public interface IDuplexServiceCallback
    {
        [OperationContract(IsOneWay = true)]
        void ConfirmAction(string message);
    }
}

サービスとホスト

namespace NetTcpDuplexService
{
    public class DuplexService : IDuplexService
    {
        public void DoAction(string message)
        {
            Console.WriteLine("DoAction: " + message);

            var callbackChannel = 
                OperationContext.Current.GetCallbackChannel<IDuplexServiceCallback>();
            callbackChannel.ConfirmAction("Ping back " + message);
        }
    }

    class Program
    {
        public static void Main(string[] args)
        {
            try
            {
                using (var host = new ServiceHost(typeof(DuplexService)))
                {
                    host.Open();

                    Console.ReadLine();
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
                Console.ReadLine();
            }
        }
    }
}

サービス構成

<configuration>
  <system.serviceModel>
    <services>
      <service name="NetTcpDuplexService.DuplexService">
        <host>
          <baseAddresses>
            <add baseAddress="net.tcp://localhost:8800/NetTcpDuplexService"/>
          </baseAddresses>
        </host>
        <endpoint address="" binding="netTcpBinding" contract="NetTcpDuplexContracts.IDuplexService" />
      </service> 
    </services>
  </system.serviceModel>
</configuration>

コールバックとクライアント

namespace NetTcpDuplexClient
{
    public class DuplexServiceCallback : IDuplexServiceCallback
    {
        public void ConfirmAction(string message)
        {
            Console.WriteLine(message);
        }
    }

    class Program
    {
        public static void Main(string[] args)
        {
            DuplexChannelFactory<IDuplexService> factory = null;

            try
            {
                var callbackService = new DuplexServiceCallback();
                var context = new InstanceContext(callbackService);

                factory = new DuplexChannelFactory<IDuplexService>(context, "IDuplexService_NetTcp");
                var channel = factory.CreateChannel();
                channel.DoAction("Hello world");

                factory.Close();
                Console.ReadLine();
            }
            catch (Exception e)
            {
                if (factory != null && factory.State != CommunicationState.Closed)
                {
                    factory.Abort();
                }

                Console.WriteLine(e.Message);
                Console.ReadLine();
            }
        }
    }
}

クライアント構成

<configuration>
  <system.serviceModel>
    <client>
      <endpoint name="IDuplexService_NetTcp" address="net.tcp://localhost:8800/NetTcpDuplexService" binding="netTcpBinding"
                contract="NetTcpDuplexContracts.IDuplexService" />
    </client>
  </system.serviceModel>
</configuration>
于 2010-08-09T16:57:17.800 に答える