WCF over net.tcp 与安全模式 none 给出异常

Posted

技术标签:

【中文标题】WCF over net.tcp 与安全模式 none 给出异常【英文标题】:WCF over net.tcp with security mode none gives exception 【发布时间】:2013-05-02 23:18:23 【问题描述】:

我们通过 WCF 使用回调来流式传输数据。 WCF 托管在 IIS 中(默认设置,只是将 net.tcp 添加到协议中)。

我们正在尝试禁用 WCF 上的安全性,因此我在客户端和服务器上都将安全模式设置为“无”,但我收到以下 CommunicationException:

套接字连接被中止。这可能是由错误引起的 处理您的消息或接收超时被超过 远程主机或底层网络资源问题。本地插座 超时为“00:00:59.8439844”。

我已经对服务进行了跟踪,并且 TraceViewer 给了我以下异常 (System.ServiceModel.ProtocolException):

需要流安全性 http://www.w3.org/2005/08/addressing/anonymous,但没有安全性 上下文进行了协商。这可能是由远程端点引起的 从其绑定中缺少 StreamSecurityBindingElement。

Client Program.cs:

using System;
using System.ServiceModel;
using WcfClient.ServiceReference1;

class Program 
    static void Main() 
        Callback callback = new Callback();
        InstanceContext context = new InstanceContext(callback);
        Service1Client service1Client = new Service1Client(context, 
                                                           "NetTcpBinding_IService1");


        service1Client.GetData(0);
        Console.Read();
        service1Client.Stop();
    


internal class Callback : IService1Callback 
    public void StreamSignalData(int[] result) 
        foreach (int i in result) 
            Console.WriteLine(DateTime.Now.ToString("dd.MM.yyyy HH:mm:ss.fff") + 
                              ": " + i);
        
    

客户端应用程序配置

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.serviceModel>
    <bindings>
      <netTcpBinding>
        <binding name="NetTcpBinding_IService1">
          <security mode="None" />
        </binding>
      </netTcpBinding>
      <wsDualHttpBinding>
        <binding name="WSDualHttpBinding_IService1">
          <reliableSession ordered="true" />
          <security mode="None" />
        </binding>
      </wsDualHttpBinding>
    </bindings>
    <client>
      <endpoint address="http://localhost/wcf-error/Service1.svc" 
        binding="wsDualHttpBinding"
        bindingConfiguration="WSDualHttpBinding_IService1" 
        contract="ServiceReference1.IService1"
        name="WSDualHttpBinding_IService1" />
      <endpoint address="net.tcp://localhost/wcf-error/Service1.svc"
        binding="netTcpBinding" bindingConfiguration="NetTcpBinding_IService1"
        contract="ServiceReference1.IService1" name="NetTcpBinding_IService1">
      </endpoint>
    </client>
  </system.serviceModel>
</configuration>

WCF Service1.svc.cs

using System;
using System.Net.Security;
using System.ServiceModel;
using System.Threading;

[ServiceContract(SessionMode = SessionMode.Required, 
                 CallbackContract = typeof(IStreamCallback), 
                 ProtectionLevel = ProtectionLevel.None)]
public interface IService1 
    [OperationContract]
    void GetData(int value);

    [OperationContract]
    void Stop();


public interface IStreamCallback 
    [OperationContract(IsOneWay = true)]
    void StreamSignalData(int[] result);


[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
[CallbackBehavior(ConcurrencyMode = ConcurrencyMode.Multiple)]
public class Service1 : IService1 
    private Timer _timer;

    private readonly IStreamCallback _callback =
            OperationContext.Current.GetCallbackChannel<IStreamCallback>();
    public void GetData(int value) 
        _timer = new Timer(StreamData, null, 0, 500);
    

    public void Stop() 
        _timer.Dispose();
    

    private void StreamData(object state) 
        int[] randomNumbers = new int[50];
        Random random = new Random();
        for (int i = 0; i < 50; i++) 
            randomNumbers[i] = random.Next(100);
        
        _callback.StreamSignalData(randomNumbers);
    

WCF Web.config

<?xml version="1.0"?>
<configuration>
  <system.web>
    <compilation targetFramework="4.0" debug="true"/>
  </system.web>
  <system.serviceModel>
    <bindings>
      <netTcpBinding>
        <binding name="netTcpBinding" >
          <security mode="None" />
        </binding>
      </netTcpBinding>
      <wsDualHttpBinding>
        <binding name="wsDualHttpBinding">
          <security mode="None" />
        </binding>
      </wsDualHttpBinding>
    </bindings>
    <protocolMapping>
      <add scheme="http" binding="wsDualHttpBinding"/>
    </protocolMapping>
    <services>
      <service name="Service">
        <endpoint address="" binding="wsDualHttpBinding" 
          bindingConfiguration="wsDualHttpBinding"
          name="EndPointHTTP" contract="WcfService1.IService1">
          <identity>
            <dns value="localhost" />
          </identity>
        </endpoint>
        <endpoint address="mex" binding="mexHttpBinding" name="mex"
          contract="IMetadataExchange" />
        <endpoint binding="netTcpBinding" bindingConfiguration="netTcpBinding"
          name="EndPointTCP" contract="WcfService1.IService1" />
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior>
          <serviceMetadata httpGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="true" />
          <useRequestHeadersForMetadataAddress />
          <dataContractSerializer />
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>
  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true"/>
  </system.webServer>
</configuration>

任何想法这可能是什么? 谷歌上的大多数点击都说客户端和服务器上的配置应该是相同的(即没有安全性),但我似乎找不到错误。 谷歌搜索 StreamSecurityBindingElement 没有找到好的解释...

【问题讨论】:

哪一方(客户端/服务)在您的日志中为您提供错误? @PetarVučetin 服务。 @PetarVučetin 我尝试在客户端上进行跟踪,但除了已经抛出的异常之外,它没有给我任何其他信息。 【参考方案1】:

我无法复制您的问题,但我有相同的设置和我注意到的几件事:

在您的 WCF Service1.svc.cs 中创建命名空间。

    namespace WcfService1
    
        [ServiceContract(SessionMode = SessionMode.Required,
            CallbackContract = typeof (IStreamCallback),
            ProtectionLevel = ProtectionLevel.None)]
        public interface IService1
        
        .....
        [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
        [CallbackBehavior(ConcurrencyMode = ConcurrencyMode.Multiple)]
        public 

    class Service1 : IService1
    

&lt;service name="Service"&gt; 应该是 &lt;service name="WcfService1.Service1"&gt;。服务名称是服务的完整类型。

配置中的服务部分:

<services>
    <service name="WcfService1.Service1">
        <endpoint address="" binding="wsDualHttpBinding"
            bindingConfiguration="wsDualHttpBinding"
            name="EndPointHTTP" contract="WcfService1.IService1">
            <identity>
                <dns value="localhost" />
            </identity>
        </endpoint>
        <endpoint address="mex" binding="mexHttpBinding" name="mex"
            contract="IMetadataExchange" />
        <endpoint binding="netTcpBinding" bindingConfiguration="netTcpBinding"
            name="EndPointTCP" contract="WcfService1.IService1" />
    </service>
</services>

WCF Service1.svc.cs

using System;
using System.Net.Security;
using System.ServiceModel;
using System.Threading;

namespace WcfService1

    [ServiceContract(SessionMode = SessionMode.Required,
        CallbackContract = typeof (IStreamCallback),
        ProtectionLevel = ProtectionLevel.None)]
    public interface IService1
    
        [OperationContract]
        void GetData(int value);

        [OperationContract]
        void Stop();
    

    public interface IStreamCallback
    
        [OperationContract(IsOneWay = true)]
        void StreamSignalData(int[] result);
    

    [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
    [CallbackBehavior(ConcurrencyMode = ConcurrencyMode.Multiple)]
    public class Service1 : IService1
    
        private Timer _timer;

        private readonly IStreamCallback _callback =
            OperationContext.Current.GetCallbackChannel<IStreamCallback>();

        public void GetData(int value)
        
            _timer = new Timer(StreamData, null, 0, 500);
        

        public void Stop()
        
            _timer.Dispose();
        

        private void StreamData(object state)
        
            int[] randomNumbers = new int[50];
            Random random = new Random();
            for (int i = 0; i < 50; i++)
            
                randomNumbers[i] = random.Next(100);
            
            _callback.StreamSignalData(randomNumbers);
        
    

回调

确保您处理 _callback.StreamSignalData(randomNumbers);当客户端断开连接时。您将收到通信异常。

【讨论】:

感谢您的意见,但不幸的是,这并没有解决我的问题 这很奇怪。好吧 - 我赢得了“它可以在我的电脑上运行”徽章:

以上是关于WCF over net.tcp 与安全模式 none 给出异常的主要内容,如果未能解决你的问题,请参考以下文章

使用 net tcp 的 WCF 双工服务:“需要流安全性...”

WCF 与 basicHttpBinding、加密、签名和 usernameToken over HTTP

WCF传输协议

如何将基于套接字的客户端与 WCF (net.tcp) 服务一起使用?

如何配置net.tcp 的WCF服务

WCF 错误“找不到与具有绑定 NetTcpBinding 的端点的方案 net.tcp 匹配的基地址”