Introduction
This is a simple chat program with a server and can have many clients. The server needs to be started first and as many client can be started then. This code uses NetTcp binding to communicate between server and client.
Background
NetTcp binding is one type binding in WCF suitable for cross-machine communication. To have the client communicate with server, CallbackContract
is used.
Using the Code
First, I have the interface called ISendChatService
with Start
, Stop
and Send
message. This interface will have service contract and also have a callback contract IReceiveChatService
. Whenever new client starts, the client will send start("LoginName")
to the server. Thereafter, the client will send message to another client by using SendMessage("Message","AnotherClientName")
. When client closes the message Stop("LoginName")
will be sent to server and server removes client from list. And list of available client list will be sent to all clients.
[ServiceContract(CallbackContract = typeof(IReceiveChatService))]
public interface ISendChatService
{
[OperationContract(IsOneWay = true)]
void SendMessage(string msg,string receiver);
[OperationContract(IsOneWay = true)]
void Start(string Name);
[OperationContract(IsOneWay = true)]
void Stop(string Name);
}
The callback interface IReceiveChatService
. ReceiveMessage
method will be used to receive a message from server sent by a client. Whenever new client is added, server will send list names.
public interface IReceiveChatService
{
[OperationContract(IsOneWay = true)]
void ReceiveMessage(string msg,string sender);
[OperationContract(IsOneWay = true)]
void SendNames(List<string> names);
}
Below is the ChatService
class which implements ISendChatService
. Here the server has a public static
event so that any client that comes in the event will fire and give the list of clients. If static
is not defined for the event, then for each client the event variable ChatListOfNames
will be null
.
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
public class ChatService : ISendChatService
{
Dictionary<string, IReceiveChatService> names =
new Dictionary<string, IReceiveChatService>();
public static event ListOfNames ChatListOfNames;
IReceiveChatService callback = null;
public ChatService() { }
public void Close()
{
callback = null;
names.Clear();
}
public void Start(string Name)
{
try
{
if (!names.ContainsKey(Name))
{
callback = OperationContext.Current.
GetCallbackChannel<IReceiveChatService>();
AddUser(Name, callback);
SendNamesToAll();
}
}
catch (Exception ex)
{
throw ex;
}
}
public void Stop(string Name)
{
try
{
if (names.ContainsKey(Name))
{
names.Remove(Name);
SendNamesToAll();
}
}
catch (Exception ex)
{
throw ex;
}
}
void SendNamesToAll()
{
foreach (KeyValuePair<string, IReceiveChatService> name in names)
{
IReceiveChatService proxy = name.Value;
proxy.SendNames(names.Keys.ToList());
}
if (ChatListOfNames != null)
ChatListOfNames(names.Keys.ToList(), this);
}
void ISendChatService.SendMessage(string msg,string sender, string receiver)
{
if (names.ContainsKey(receiver))
{
callback = names[receiver];
callback.ReceiveMessage(msg, sender);
}
}
private void AddUser(string name,IReceiveChatService callback)
{
names.Add(name, callback);
if (ChatListOfNames !=null)
ChatListOfNames(names.Keys.ToList(), this);
}
}
Coming to the client, I just implemented the ISendChatService
interface. I added two delegates ReceviedMessage
and GotNames
for ReceiveMsg
and NewNames
events. The event ReceiveMsg
will receive message from any client and the event NewNames
will get newly added or deleted client.
public delegate void ReceviedMessage(string sender, string message);
public delegate void GotNames(object sender, List<string /> names);
class ReceiveClient : ChatService.ISendChatServiceCallback
{
public event ReceviedMessage ReceiveMsg;
public event GotNames NewNames;
InstanceContext inst = null;
ChatService.SendChatServiceClient chatClient = null;
public void Start(ReceiveClient rc,string name)
{
inst = new InstanceContext(rc);
chatClient = new ChatService.SendChatServiceClient(inst);
chatClient.Start(name);
}
public void SendMessage(string msg, string sender,string receiver)
{
chatClient.SendMessage(msg, sender,receiver);
}
public void Stop(string name)
{
chatClient.Stop(name);
}
void ChatService.ISendChatServiceCallback.ReceiveMessage(string msg, string receiver)
{
if (ReceiveMsg != null)
ReceiveMsg(receiver,msg);
}
public void SendNames(string[] names)
{
if (NewNames != null)
NewNames(this, names.ToList());
}
}
In the web config file, I set binding as netTcpBing
. Please add your IP in the place of localhost in the baseAddress
.
<div>
<configuration>
<system.serviceModel>
<services>
<service name="Server.ChatService"
behaviorConfiguration="ChatServiceBehavior">
<host>
<baseAddresses>
<add baseAddress="net.tcp://localhost:1234/Chat/ChatService"/>
</baseAddresses>
</host>
<endpoint address="" binding="netTcpBinding"
bindingConfiguration="Binding1"
contract="Server.ISendChatService">
</endpoint>
<endpoint address="mex" binding="mexTcpBinding"
contract="IMetadataExchange"/>
</service>
</services>
<bindings>
<netTcpBinding>
<binding name="Binding1" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:10:00"
sendTimeout="00:01:00" transactionFlow="false" transferMode="Buffered"
transactionProtocol="OleTransactions" hostNameComparisonMode="StrongWildcard"
maxBufferPoolSize="524288" maxBufferSize="65536" maxConnections="10"
maxReceivedMessageSize="65536">
<security mode="None">
<message clientCredentialType ="UserName"/>
</security>
</binding>
</netTcpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="ChatServiceBehavior">
<serviceMetadata httpGetEnabled="False"/>
<serviceDebug includeExceptionDetailInFaults="False"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
</div>
Example Project
The example project consists of three project files. Please install the server on a machine. Compile the solution. Run the server EXE and click start. Update the service in client by right clicking service and click Update Service. After that, you can open many clients.
Conclusion
The webconfig file can be encrypted.