WCF With NetTCP across machines on the same network
Asked Answered
P

2

6

I'm trying to implement some cross process communication that is between multiple computers and one server on the same network. What I'm trying right now is to use WCF with NetTcpBinding, hosted within my application which works on the same machine, but when I try to connect from another machine it throws a SSPI security error.

I've found lots of examples of doing this cross-machine, but all involve an app.config file which I would REALLY like to avoid. I want to be able to embed this functionality in a DLL that has not other dependencies (i.e. config files) for which I can just pass into it all of the necessary server addresses, etc and it will work. Is there anyway to setup this security (via the endpoints, etc) purely in code?

I'm testing this all out with the code below:

SERVER:

using System;
using System.ServiceModel;

namespace WCFServer
{
  [ServiceContract]
  public interface IStringReverser
  {
    [OperationContract]
    string ReverseString(string value);
  }

  public class StringReverser : IStringReverser
  {
    public string ReverseString(string value)
    {
      char[] retVal = value.ToCharArray();
      int idx = 0;
      for (int i = value.Length - 1; i >= 0; i--)
        retVal[idx++] = value[i];

      string result = new string(retVal);
      Console.WriteLine(value + " -> " + result);
      return result;
    }
  }

  class Program
  {
    static void Main(string[] args)
    {
        var uri = "net.tcp://" + System.Net.Dns.GetHostName() + ":9985";
        Console.WriteLine("Opening connection on: " + uri);

      using (ServiceHost host = new ServiceHost(
        typeof(StringReverser),
        new Uri[]{
          new Uri("net.tcp://" + System.Net.Dns.GetHostName() + ":9985")
        }))
      {
        host.AddServiceEndpoint(typeof(IStringReverser),
          new NetTcpBinding(),
          "TcpReverse");

        host.Open();

        Console.WriteLine("Service is available. " +  
          "Press <ENTER> to exit.");
        Console.ReadLine();

        host.Close();
      }
    }
  }
}

CLIENT:

using System;
using System.ServiceModel;
using System.ServiceModel.Channels;

namespace WCFClient
{
  [ServiceContract]
  public interface IStringReverser
  {
    [OperationContract]
    string ReverseString(string value);
  }

  class Program
  {
    static void Main(string[] args)
    {
        var ep = "net.tcp://SERVER:9985/TcpReverse";
      ChannelFactory<IStringReverser> pipeFactory =
        new ChannelFactory<IStringReverser>(
          new NetTcpBinding(),
          new EndpointAddress(
            ep));

      IStringReverser pipeProxy =
        pipeFactory.CreateChannel();

      Console.WriteLine("Connected to: " + ep);
      while (true)
      {
        string str = Console.ReadLine();
        Console.WriteLine("pipe: " + 
          pipeProxy.ReverseString(str));
      }
    }
  }
}
Paraphernalia answered 1/8, 2011 at 20:25 Comment(1)
I'm doing something similar to this however I always get a timeout Exception even if the function I try to call only has the line return -1; and have the sendtimeout set to 1 hour the only main difference is I have used basic http instead of tcp any ideas on what I may need to do.Adolf
E
5

Security is normally configured on the binding. You are using NetTcpBinding with its defaults which means that Transport security is enabled.

On both, server and client, you should assign the NetTcpBinding instance to a local variable so that you can change the security (and possibly other) settings, and then use that variable when calling AddServiceEndpoint or when creating the ChannelFactory.

Sample:

var binding = new NetTcpBinding();
// disable security:
binding.Security.Mode = SecurityMode.None;
Epidiascope answered 1/8, 2011 at 20:51 Comment(1)
+1 Perfect! Just what I was looking for with NetNamedPipeBinding as well!Newcastle
M
1

This is probably an issue with the SPN that your service is running under. It's most likely a machine account instead of a domain account. There's more information in this thread.

UPDATE: There's information in there about setting the SPN programmatically, but it's buried a few clicks in... here's a direct link (see the last section of the page).

Mugwump answered 1/8, 2011 at 20:49 Comment(1)
Tried to get this working but still had no luck... though I would like to make it work this way. I guess maybe I just don't understand what to use for the DNS identity. They use "contoso.com" but not sure how that translates to my setup.Paraphernalia

© 2022 - 2024 — McMap. All rights reserved.