Introduction

This application is built on the WCF .NET Framework 3.0. It uses duplex communication and TCP binding (for some reasons that are discussed later in this article). It concentrates on handling and controlling a WCF service that has to make reliable sessions with many clients and keep those connections alive as long as possible.

The application UI is built on WPF .NET Framework 3.0, and here I have to say that I am not good in WPF, and I haven't used animations; I just wanted it to look better, so I chose WPF.

As Sacha explains here, it is a great application (and Sacha is really smart -I love this man-).

The WCF Chat mechanism developed by Nikola and Sacha is a great technique, but it is complex somehow; I wasn't able to understand Sacha's article the first time I read it, that's why I decided to make this simple and step by step.

Note that this article uses client-server pattern and not peer to peer.

In this article, you are going to learn how to:

Create a service and configure it to use TCP binding.

Host a service and manually control it.

Define service contracts, duplex, and data contracts.

Implement a reliable session between the service and the client, and keep it alive for a long time.

Increase max connections, let's say to 100.

Handle the communication state in the client application.

Asynchronously call service operations.

Enable the service to be accessed online.

The application features include:

Connect to the service and disconnect, offline from inside a network or online from the internet.

Choose nickname and avatar.

Participate in public chat, or whisper in private chat.

Know if someone is writing a message.

Know if the service stopped or disconnected.

Reconnect after faults.

File transfer (updated).

Updates

File transfer enabled

Technique

This service is a singleton service; every client starting a session does not instantiate a new instance of the service. This is to enable a single service to deal with many clients. This means that the first client calling the service instantiates a new instance of the service, and each subsequent call is just calling the service operations. Service operations are methods or functions that the service implements; a service represents its operations in an interface, and represents the callback operations in another interface, asking a client to implement those callback operations, to be able to call the client again whenever it may want.

So, you have got to know:

Contracts:Contracts in Windows Communication Foundation provide the interoperability they need to communicate with the client. It is through contracts that clients and services agree as to the types of operations and structures they will use during the period that they are communicating back and forth. Without contracts, no work would be accomplished because no agreement would happen (Wrox Professional WCF Programming). In our case, we define the service operations that we want the service to implement, in an interface, and define the operations that the service wants the client to implement in another interface called the callback interface, this is where they both agree through contracts.

EndPoints: The service must define at least one EndPoint and apply binding to it.

Bindings: WCF has some predefined bindings that are really useful and can fit many cases. In our case, we are going to use netTcpBinding which allows duplex communications (the red EndPoint in the image above), and mexTcpBinding to support publishing service metadata (the blue EndPoint in the image above).

Addresses: Services have to define an address for every EndPoint (we will go through base addresses later), so it can be called from, and here we have three addresses, one on TCP protocol to call the service, one on TCP protocol to publish metadata, and one on HTTP protocol to enable HTTP GET for metadata. And you (the developer) is the one who defines the service address (it doesn't relate to any other names, or paths, you just define a new address like http://localhost/blablabla/myService.svc and it will work).

Step by step, Building a WCF duplex service

Steps in points:

Create service assembly:

Data contracts

Service contract

Callback contract

Concurrency handling

Service implementation

Create Host on WPF:

ServiceHost class

Binding configuration in config file

Binding configuration programmatically

BaseAddresses

Enable metadata configuration in config file

Enable metadata configuration programmatically

Reliable Sessions

Max Connections

Create Client on WPF:

Generate proxy

Add avatars as embedded resources

Proxy duplex channel state handling

Asynchronously calling service operations

Implement callback interface

Other stuff:

Enable online access (port forward and firewalls)

Automatically locating service IP

Create service assembly

Create a new folder in the C: directory and name it WCFWPFRoot.

Fire up Visual Studio, File > New > Project, choose C# Class Library.

Set the solution name to WCFWPFApp and the project name to ServiceAssembly; the location is the WCFWPFRoot folder.

Rename Class1.cs to ChatService.cs.

Remove:

using System.Linq;
using System.Text;

Right click the project name, choose Add Reference.. , and add a reference for System.ServiceModel.

Now, we will start to add some interfaces and other classes beside this class (ChatService) in the ServiceAssembly namespace. The first class we will add is a Data Contract; a data contract means an agreement to transfer this type of data.

To add a Data Contract, add a reference to System.Runtime.Serialization, and so add this line: using System.Runtime.Serialization;.

Our data will be of two types, the first one represents a client and consists of name, avatar ID, and time; so we design the client to be like this:

For designing a service contract, we need to know how the client is going to interact with the service. Here, we specify that a client has to start a session with the service, and terminate this session by calling some operations that can really start and terminate a session (this is why we set SessionMode = SessionMode.Required). Well, how can a service start a session or terminate it? The answer is, just by setting two properties (IsInitiating or IsTerminating) in the OperationContract attribute, and the WCF runtime will understand this. Operations can be one-way (void); this has an advantage that a client can call the operation and proceed its process without waiting for a reply from the service. In our contract, all operations are one-way except for the Connect operation; it returns a boolean to know if the client has been successfully joined, or the client name has been found and already exists. The last thing is to reference the Callback interface, which is the interface the client will implement: CallbackContract = typeof(IChatCallback).

Designing a callback interface is very easy; just want an interface to define some operations to be called on the client side.

The service is responsible for defining these parameters and calling those operations.

Time for the service implementation (of IChat interface). Our service contains a generic dictionary of key types of clients and value types of IChatCallback; so this generic collection will hold the online clients as keys and callback objects for each client as values. The service also contains a generic list to hold the online clients (to quickly pass it to users), a public property that represents the current callback object, a private method used by the service to search for a client in the clients list, and an object to synchronize our work - this object is useful to lock the current thread from receiving calls from clients and wait for the current operation to be completed. We will need this because in the service context, you might be sending some information for each callback object using a foreach loop, and suddenly one of these callback objects' client might get disconnected, and the operation won't complete because the collection has been modified and a client has been removed from it.

Well, this brings us to talk about handling concurrency on the service. A WCF service can handle concurrency in three different ways. The Single and Reentrant options use a synchronized pattern to handle incoming calls from clients, but this can make a deadlock if a client tries to call a service and waits for a reply, the service processes the client request and needs to call the client back again, but the client is still waiting for a reply from the service, and thus causing a deadlock. The Reentrant option will make the WCF release the lock, but we will use the Multiple option which allows to make calls on another thread (this is good, but needs us to synchronize our code as we said before).

This is our host application that should instantiate a ServiceHost object. A ServiceHost object is what will actually host your service, enable you to apply bindings, add EndPoints, start the service or stop it. So, we will start defining a ServiceHost programmatically, and then use the configuration file.

Create client on WPF

File > Add > New Project.., choose WPF Application, and set its name to WPFClient.

Add a reference to System.ServiceModel.

Set the WPFHost project to be the startup project, start it, hit the Start button to run the service.

Set the WPFClient project to be the startup project, and add a service reference, as in this picture:

As you see, we give it the address of the mex (our metadata) EndPoint, and it will know and configure a new config file with the address of the TCP EndPoint. Click Advanced to enable asynchronous operations and generic lists.

Now, hit OK and you will notice that a new app.config file has been added. Open it and modify the binding to enable file transfers of 64 MB, and increase max connections to 100.

Other stuff

Enable online access over the Internet

If your server (the machine that will run the service application) is inside a network, you have to forward the port that the service listens on (in our case, it is 7997). To do this, login in to your router configuration, and port forward 7997 (Help).

You may also want to open this port manually, or create a rule for it in your firewall. I use Kaspersky Internet Security

.

Automatically locate service IP

You can automatically locate your service by saving an always-updated IP in a text file, uploading it online, and letting your client applications read the IP from the uploaded text file..

Feedback

These distributed applications are built on a learning experience. I wanted to share the code to learn more and let others learn too, so if you got problems, errors, ideas, please let me know. If you liked it, please vote. Thanks.

Hello Mr. Islam
please i want to know if there's any possibility to add voice chat to this application via WCF Stream ?
If yes, what are the procedures i should take to accomplish this and what methods should i modify ?
waiting for your reply
regards

When we access the chat through an internet connection it takes lot of time to send large files and in the middle of the SendFile method the proxy_SendFileCompleted event fires.It can be regenerated adding a break point inside the SendFile method in the debug mode.In this case accessing e.Results gives an error since results object is null.Could anybody give an explanation to this scenariao.