0

我的目标是在没有打开传入端口的情况下访问防火墙后面的 WCF 服务。我选择的解决方案是在公共端托管双工 WCF 服务,该服务具有与不涉及防火墙时使用的相同合同作为回调。

如果我使用 netTcpBinding 它可以工作,但由于我需要流式通信,所以我必须使用自定义绑定。

一切正常,直到我提高防火墙。此时,直接调用(从防火墙后面)工作正常,但回调不能(防火墙阻止它)。

问题是为什么?他们不应该使用与预定义的 netTcpBinding 相同的频道吗?

这是我在 app.config 中的频道堆栈:

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

1 回答 1

2

实际行为是正确的。您已经使用了compositeDuplex 绑定元素- 复合词的含义正是您所得到的- 两个独立的通道,每个通道都用于一个方向。只有默认不支持双工通信的传输通道才需要复合双工。这不是 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 回答