7
votes

We are streaming data with WCF using callbacks. The WCF is hosted in IIS (default settings, just added net.tcp to protocols).

We are trying to disable security on the WCF, so I've set security mode to "none", both on the client and the server, but I get the following CommunicationException:

The socket connection was aborted. This could be caused by an error processing your message or a receive timeout being exceeded by the remote host, or an underlying network resource issue. Local socket timeout was '00:00:59.8439844'.

I've put on tracing on the service and the TraceViewer gives me the following exception (System.ServiceModel.ProtocolException):

Stream Security is required at http://www.w3.org/2005/08/addressing/anonymous, but no security context was negotiated. This is likely caused by the remote endpoint missing a StreamSecurityBindingElement from its binding.

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);
        }
    }
}

Client App.Config

<?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>

Any ideas what this might be? Most of the hits on google say that the configuration on the client and the server should be the same (i.e. security to none), but I can't seem to find the error. Googling for StreamSecurityBindingElement came up with no good explenations...

1
Which side (client/service) gives you the error in your log?Petar Vučetin
@PetarVučetin The service.user866852
@PetarVučetin I tried putting on tracing on the client, but it doesn't give me any other information than the exception it's already throwing.user866852

1 Answers

1
votes

I could not replicate your problem but I have same setup and few things I noticed:

Create namesapace in your 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
    {

<service name="Service"> should be <service name="WcfService1.Service1">. Service name is full Type for the service.

Services section in config:

<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

Make sure you handle _callback.StreamSignalData(randomNumbers); when client disconnects. You will get a communication exception.