SingingEels : Development Community & Resource

Login

Articles

  • ADO.NET (2)
  • ASP.NET (36)
  • Azure (0)
  • LINQ (5)
  • Security (2)
  • Silverlight (3)
  • SQL (7)
  • Standards (5)
  • WCF (2)

Syndication

  • Articles RSS
  • Blogs RSS

Contribute

  • Our Authors List
  • Member Sign-Up
  • Suggestions Box

Client Server Programming with WCF

(Apr 03 2008 - 04:46:38 AM by Timothy Khouri) - [print article]

Client/server programming isn't a new concept. In fact, it's been around so long that developers can quickly mention a set of problems that will need to be overcome: security, difficulty of implementation, error handling and identity tracking. This article will show how WCF (Windows Communication Foundation) quickly solves all of that and more.

First, lets consider a few other options that have been out there before WCF came about. We'll consider building things "from scratch" by using plain old TCP sockets (which can be implemented in almost any language and environment). Next, we'll talk a little about .NET Remoting and how this made things a lot simpler in terms of development, but was lacking some key functionality, and even caused some big design problems. Finally, we'll compare these two methods (and any similar choices) to using WCF.

Using TCP Socket Connections

TCP connections offer a developer a "raw" methodology for communicating with other computers around the world. While .NET helps with making setup easier by means of the TcpClient and TcpListener classes, you're still left with providing your own means for security, error handling and more importantly, translation of the packets of data.

Because socket connections ultimately just give you the ability to send "bytes" of data across a wire, you're left with this:

byte[] buffer = new byte[1024];

int numberOfBytesRecieved = myTcpSocket.Receive(buffer);

// Yay, now I have some bytes of data... now what?

In order to turn this data into something useful you'll get to enjoy creating several methods just for the sake of re-polling to get the entire message, parsing the data to see what "command" was being sent and reconstructing the parameters into tangible objects.

Other frustrations that come up with using plain old sockets is that you have to constantly check for connection errors. There's no event that fires to let you know when someone disconnected abruptly. As a result, the next time you go to read from the stream, crash, you just got an error.

When you see all the other beautiful classes in the .NET framework, you have to be thinking at this point, "there's gotta be a better, object oriented way to develop connected applications." And there is!

.NET Remoting - A Half-Way Solution

When Microsoft came out with remoting in .NET, suddenly things got a lot easier. Now, instead of raw packets coming across a wire, you were calling actual methods, passing in CLR objects as parameters that would automatically get serialized, transmitted and deserialized on the client end. Once you got the basic framework setup (which isn't very difficult), you could do things like this:

// Assuming that I did some code above here to create my
// remoted object...


myRemotedObject.Authenticate("tkhouri", "ubberGuy!");

Client[] clients = myRemotedObject.GetClients();

Please note that these methods are completely made up, but the idea is that the .NET framework took care of all the nasty "raw tcp data" stuff for you, and (behind the scenes) executed your code on the server and returned the result back to your client application.

So you may be saying, "why did we need WCF if we already had .NET Remoting?" There are a lot of good answers to that question, but the ones that I key in on are these:

  1. .NET Remoting doesn't support two-way communication, whereas WCF does! This means that you can call code from the client to the server, but the server can't call a function back on the client.
  2. .NET Remoting doesn't have built in events that let the server know when a connection has faulted or closed, nor does it give you a concrete object that represents the connected client as an object. This is important when you want to know for sure when a client has disconnected, even if that was due to an error, to remove it from a list of connected clients (or whatever).
  3. WCF provides out-of-the-box security measures to ensure that users don't have access to certain functionality until they first "Initiate" and that they can't call privileged methods after they "Terminate."

Basic WCF Infrastructure and Setup

Making a client/server program using WCF is fairly straight forward. We're going to make a server program (a basic Console application), a client program (another Console application) and a communication interface (a class library) to hold common object definitions.

The "service" (or server) will need to be configured to tell WCF the address and port that will be accepting clients. This can be done in code (programmatically), or through the app.config in the "System.ServiceModel" configuration section. Here's how we configured our server:

<configuration>
   <system.serviceModel>
       <!-- Setup information for the client to find the server. -->
       <services>
           <service name="WCF_Server.SingingEelsServer">
               <endpoint
                   address="net.tcp://localhost:3315/EelsServer"
                   binding="netTcpBinding"
                   contract="WCF_Interface.ISingingEelsServer"
                   bindingConfiguration="InsecureTcp" />
           </service>
       </services>

       <!-- For simplicities sake, we're not going to use any security measures. -->
       <bindings>
           <netTcpBinding>
               <binding name="InsecureTcp">
                   <security mode="None" />
               </binding>
           </netTcpBinding>
       </bindings>
   </system.serviceModel>
</configuration>

There's really not a lot going on here. First we configure the service that we will be hosting. In the <service> configuration section, we set the "name" attribute to the class type that we will be hosting. Then, we configure an <endpoint> to tell WCF what address (and port) should map to our service.

The "contract" attribute is the interface that we defined in our class library that both the server and the client have a reference to. Finally, we are going to setup a bindingConfiguration attribute to turn off any encryption or security. This is just to make things easy for our demo.

The client configuration will look very similar to this one, except that it will define the "<client>" tag instead of the "<services>" tag in the app.config. Here's what the client config would look like:

<!-- This would replace the 'services' section in the server. -->
<client>
   <endpoint
       name="SingingEelsWcfServer"
       address="net.tcp://localhost:3315/EelsServer"
       binding="netTcpBinding"
       contract="WCF_Interface.ISingingEelsServer"
       bindingConfiguration="InsecureTcp" />
</client>

WCF Server Code

Now that our application is configured to host a service, how do we begin accepting connections in the server? Well, the code itself is very simple. Due to saving some space in this article, I'll explain most of it, and then show you just a little to get you excited. At the end of the article will be a full source code example that you can download (a Visual Studio 2008 solution).

First of all, we would need to build our interfaces that will describe what methods are going to be exposed through the service. Also, we'll have to decorate them with a few attributes to tell WCF how to handle the communication. Here is a the server interface code:

using System;
using System.ServiceModel;

namespace WCF_Interface
{
   [ServiceContract(CallbackContract = typeof(ISingingEelsUser), SessionMode = SessionMode.Required)]
   public interface ISingingEelsServer
   {
       [OperationContract(IsInitiating = true)]
       bool Authenticate(string userName, string password);

       [OperationContract(IsInitiating = false)]
       string[] GetFavoriteWebsites();

       [OperationContract(IsInitiating = false, IsTerminating = true, IsOneWay = true)]
       void Disconnect();
   }
}

The key attributes here are:

  • ServiceContract - This tells WCF that the interface can be used as a WCF service. It also says what type of object will be used as a callback to the client in the event of a DuplexChanelBase being used. This is what I was mentioning before that .NET Remorting was missing.
  • OperationContract - This attribute basically says "I want to be able to call this method." If you notice, we explicitly say which method is the "initiating" method, and which is the "terminating" one. This means that a client MUST call the Authenticate method first, and that if he calls Disconnect, the connection will end. Again, these built in security functions are not available in .NET Remoting (and certainly not with plain sockets).

After we create our interface objects, we'll now need to create an actual concrete implementation on the server. It will need to implement the ISingingEelsServer interface. Because the app.config file tells WCF how to map that class to the service, nothing more is needed.

WCF Client Code

The client has a little bit more work to do, but not much. It has to create a local representation of the server as well. This class will inherit from System.ServiceModel.DuplexClientBase, which is a generic class, and it will impliment the server interface.

You may be asking, "why do I have to write the server code on the client!?" And the answer is, you don't. All you are doing here is tapping into the WCF object and giving yourself a wrapper class in case you want to do some other functionality in there. When you see the code, it'll make more sense, so here it is:

using System.ServiceModel;
using WCF_Interface;

namespace WCF_Client
{
   public class SingingEelsServerConnection : DuplexClientBase<ISingingEelsServer>, ISingingEelsServer
   {
       // Because we are using DuplexClientBase, we need to

       // provide an object to the server that will act as

       // the callback to the client.

       public SingingEelsServerConnection(ISingingEelsUser callbackInstance)
           : base(callbackInstance)
       {
           //

       }

       public bool Authenticate(string userName, string password)
       {
           return base.Channel.Authenticate(userName, password);
       }

       public string[] GetFavoriteWebsites()
       {
           return base.Channel.GetFavoriteWebsites();
       }

       public void Disconnect()
       {
           base.Channel.Disconnect();
       }
   }
}

Wrapping It All Up

That's basically the end of it. Now, in your server you simply start "listening" for connections, and in the client code, you make an instance of your SingingEelsServerConnection class and start calling methods. To see how simple it all is, you can download the source code at the end of this article (which we are rapidly approaching).

Please keep in mind that there is a LOT more to WCF than I'm showing here. There will be more advanced articles that will explain features of WCF in more detail, but for now, you can see how to quickly setup a client/server model and begin programming.

Earlier I mentioned that there are events that you can tap into to see if a user disconnects or errors, and those events are:

  • OperationContext.Current.Channel.Faulted - Gets called when there is an error on the client's end having to do with the connection. This will get called even if you physically cut your network cable.
  • OperationContext.Current.Channel.Closed - Gets called when the connection from the client is closed for any reason. So if you want to clean up some resources made by the connection (whether it's closed gracefully, or via an error) here's where you would put your code.

Last of all, here's the source code for. Check it out for yourself if you have any questions: SingingEels_WCF_Basic_Client_Server.zip

  • Jul 24 2008 - 11:42:21 PM nandita

    Hi,

    I want to see the list of WCF operations in WCF published metadata in IE. The App.config of host application looks like as below. With ihis servicebehaviour settings , it shows the mettadata in IE as follows. Please reply me on nanditar@datacom.co.nz

    ----------

    App.config

    -----------

    <?xml version="1.0" encoding="utf-8" ?>

    <configuration>

    <system.serviceModel>

    <behaviors>

    <serviceBehaviors>

    <behavior name="HTTPBehaviour">

    <serviceMetadata httpGetEnabled="true" httpGetUrl=""/>

    </behavior>

    </serviceBehaviors>

    </behaviors>

    <services>

    <service name="IRIS.Services.Consent.Core.ConsentService" behaviorConfiguration="HTTPBehaviour">

    <endpoint contract="IRIS.Services.Consent.Interface.IConsentService" binding="basicHttpBinding"/>

    </service>

    </services>

    </system.serviceModel>

    </configuration>

    ---------------------------

    Published Metadata:

    ----------------------------

    You have created a service.

    To test this service, you will need to create a client and use it to call the service. You can do this using the svcutil.exe tool from the command line with the following syntax:

    svcutil.exe http://localhost:8080/ConsentService?wsdl

    This will generate a configuration file and a code file that contains the client class. Add the two files to your client application and use the generated client class to call the Service. For example:

    C#

    class Test

    {

    static void Main()

    {

    ConsentServiceClient client = new ConsentServiceClient();

    // Use the 'client' variable to call operations on the service.

    // Always close the client.

    client.Close();

    }

    }

    Visual Basic

    Class Test

    Shared Sub Main()

    Dim client ConsentServiceClient = New ConsentServiceClient()

    ' Use the 'client' variable to call operations on the service.

    ' Always close the client.

    client.Close()

    End Sub

    End Class

  • Oct 24 2008 - 06:14:46 AM pcn123

    Excellent article. thanks a lot.

    /pcn

  • Jul 15 2010 - 10:36:28 AM gopalb85

    Nice Article

You must be logged in to add comments. If you have not already done so, you can create an account here. If you already are a member, you first need to login before you can comment.

Developer / Architect / Author

Check Out Dev++

Test your development skills, give proof to recruiters and employers at dev++

Related Blogs

These are the most recent blog posts related to this article.

  • Silverlight Beta Has WCF, LINQ, Windows Controls!

Related Ads

SingingEels.com as of Feb 04 2012 - 12:26:30 AM - (0.0625004)