Mono WCF Advent Day 11: NetTcpBinding

| 6 Comments | No TrackBacks

Until today I have explain only two Bindings (or three): BasicHttpBinding and WebHttpBinding (and CustomBinding if it counts). But as I implied earlier, we have more. Today I'd explain TCP transport and NetTcpBinding and couple of new things.

In short, NetTcpBinding is WCF-only, non-interoperable binding based on binary messages and TCP transport.

Binary XML serialization

"Binary XML" is not really XML. It is fake, a buzzword. It actually means, a binary representation based on XML Infoset (or something, depending on what it would describe). In WCF land, binary XML usually means an XML binary format used by XML reader and writer from XmlDictionaryReader.CreateBinaryReader() and XmlDictionaryWriter.CreateBinaryWriter().

While we have corresponding implementation since 2005, its data format has been recently published as [MC-NBFX] as part of Microsoft's Windows Protocol documentation.

In WCF, there is BinaryMessageEncodingBindingElement that uses this binary XML representation to serialize and deserialize messages. You can explicitly use it as message encoder part of your binding (using CustomBinding) as I did on Day 3. NetTcpBinding uses this one without customization.

Request/Response vs. Duplex

Message transport protocol also involves its own binary representation, but I have to explain "channel types" in prior. Until today I haven't explain about channel types, in other words types of IChannel interface variety - as BasicHttpBinding and WebHttpBinding are both for request-reply style communication. WCF is not only about it - it actually supports:

  • request-reply messaging: represented as IRequestChannel and IReplyChannel. A client sends a request to a server, then the server receives it and sends reply back to the client, and the client receives it.
  • simplex messaging: represented as IOutputChannel and IInputChannel. A client sends a message to a server, then the server receives it. No further communication is performed.
  • duplex messaging: represented as IDuplexChannel. Either of the communication sides may perform simplex messaging.

They may also involve sessions and in such case they become IFooSessionChannel (e.g. IRequestSessionChannel). To know which kind of messaging is supported by the Binding you are using, you can use CanBuildChannelFactory<TChannel>() method for clients or CanBuildChannelListener<TChannel>() method for servers.

It may look strange, but duplex messaging could be still used to support service method that has both invocation parameters (request) and return value (reply).

TCP binary data exchange

Back to NetTcpBinding, it supports two kinds of above, under different configuration; NetTcpBinding has TransferMode property and it indicates the communication channel style. If the property value is TransferMode.Streamed, then it creates request-reply type channel. If it is TransferMode.Buffered, then it results in duplex channel. While duplex channel could be used for RPC-style service calls, the underlying communication protocol becomes different. So you have to adjust the transfer mode between client and server.

The communication protocol is also documented, as [MC-NMF] and some related docs in Windows Protocol documentation.

NetTcpBinding example

Here is an example pair of NetTcpBinding client and server, using buffered == duplex communication mode.

[NOTE] It turned out that I brought some regressions which broke some binary message communication. It has been a while since I have implemented a couple of months ago. I've been fixing some bugs these days.

// client
using System;
using System.Xml;
using System.ServiceModel;
using System.ServiceModel.Channels;

public class Test
{
  public static void Main ()
  {
    var binding = new NetTcpBinding ();
    binding.Security.Mode = SecurityMode.None;
    var endpoint = new EndpointAddress ("net.tcp://localhost:8080/");
    var proxy = new ChannelFactory<IFoo> (binding, endpoint).CreateChannel ();
    Console.WriteLine (proxy.Echo ("TEST FOR ECHO"));
    Console.WriteLine (proxy.Add (1000, 2000));
  }
}

[ServiceContract]
public interface IFoo
{
  [OperationContract]
  string Echo (string msg);

  [OperationContract]
  uint Add (uint v1, uint v2);
}
// service.cs
using System;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;

public class Tset
{
  public static void Main ()
  {
    ServiceHost host = new ServiceHost (typeof (Foo));
    NetTcpBinding binding = new NetTcpBinding ();
    binding.Security.Mode = SecurityMode.None;
    var uri = new Uri ("net.tcp://localhost:8080");
    host.AddServiceEndpoint ("IFoo", binding, uri);
    host.Open ();
    Console.WriteLine ("Hit [CR] key to close ...");
    Console.ReadLine ();
    host.Close ();
  }
}

[ServiceContract]
public interface IFoo
{
  [OperationContract]
  string Echo (string msg);

  [OperationContract]
  uint Add (uint v1, uint v2);
}

class Foo : IFoo
{
  public string Echo (string msg)
  {
    return msg;
  }

  public uint Add (uint v1, uint v2)
  {
    return v1 + v2;
  }
}

Limitation

.NET NetTcpBinding is actually capable of handling some complicated things such as message security, but we don't provide message security support yet. If you have NetTcpBinding configured to use message security, NetTcpBinding.Security.Mode has to be set as None.

No TrackBacks

TrackBack URL: http://veritas-vos-liberabit.com/monogatari/mt-tb.cgi/95

6 Comments

It's more than strange that duplex messaging could be used to support service method with both invocation parameters. Are you sure it works properly?

Oops, I didn't visit my blog long. Try it on .NET.

This example doesn't work on the latest mono 2.8.X version on Mac. Please advise the possible workaround . Your help is really appreciated.

Very thanks for articles !!!

Did you ever resolve this issue, if so I'd be interested to know how.

What do you mean by "this issue" ?

Leave a comment