Message System: Carbonum Labs
Message System: Carbonum Labs
Carbonum Labs
www.carbonum.com
Copyright (c) 2009-2014
[MESSAGE SYSTEM]
Creating a Message System with Port Manager 2010.
Message system
Message System
In this example we build a basic messaging system using UDP ports. The main focus will be placed
in the following topics:
Remember UDP is a connectionless protocol, however the PortManager still handles UDP end
points as if they where connections. UDP server ports have an IDLE timer (connection timeout) if
the UDP server detects that a given end point has been silent for more than the specified timeout,
it will consider the end point as “disconnected”; at this moment it will issue the OnStateChanged
event and release all associated resources.
The Protocol
We will have a simple text based protocol to communicate our client and server applications. UDP
gives no guaranties about packet delivery, order or integrity, however in order to simplify this
example we will assume no packets can be lost in the network so there will be no need to handle
acknowledges nor retries for ourselves. If this cannot be guaranteed in your environment, switch
to TCP ports or design and implement a robust protocol that is capable of solving these problems
to some extent.
To begin with, any client connected to the server will have to provide a nickname before sending
any messages. We will keep track of this nickname using the UserState property found in each
active connection. After that, each client will simply send any message the user types to the
server, and also show on the screen the messages the server will send to it.
All messages in the protocol start with the delimiter "$m[" and ends with "]\r\n". The general
structure of a message is as follows:
$m[COMMAND,ARG1,ARG2,...,ARGN]\r\n
Where:
• COMMAND is the name of the command being issued to the server or client.
• And ARG1, ARG2, and so on, are arguments required by the command in order to be
executed. These arguments should be scaped to avoid potential parsing problems using
the following scape sequences:
Page 2
Message system
Registration Command
This command allows a client to register its nickname within the server. This should be the first
command sent by any client before sending any other command.
$m[REGISTER,Nickname]\r\n
Please note that to avoid unnecessary complexity we are not authenticating users, nor validating if
they are already registered in a different end point (or active connection).
$m[SEND,mensaje]\r\n
Whenever a message is sent to the server, the server will append the name of the user that is
sending it, and broadcast to all connected users using the same Send command (this includes the
original sender).
Disconnect command
Since UDP is a connectionless protocol, before any client decides to go away it’s a good idea to tell
the server we are no longer interested in receive any more massages. The disconnect command
enables a client to notify the server it should dispose any resources associated to its connection.
$m[DISCONNECT]\r\n
Server application
Create a new solution and add a new windows application project to it, name it
“MessageSystemServer”. This project will be our server application. The main form in this project
should have the layout shown in figure 1. Notice we have already added the Port Manager
component in the tray area of the form designer.
Page 3
Message system
Right click the Port Manager component and select the Port configuration option from the
contextual menu that shows up. Once there, add a new server port using the UdpServer interface
(if you wish you can use the TcpServer interface instead since we are not really taking any
advantage of the udp protocol here). Make sure to set the timeout property to zero (disabled).
Also add the message delimiter (“$m[“, “]\r\n”) as shown in figure 2.
As we mentioned before we are going to keep track of state information for each connected client
using the UserState property of each active connection found in the server port we just created. In
this example the user state object will be used simply to remember the nickname of the user that
is connected at the end point. We will store this information in a separate class of type
“MsgSrvUserState” shown below:
class MsgSrvUserState
{
private string nickname;
public MsgSrvUserState()
{
}
Page 4
Message system
Open the port configuration screen again, select the server port and then click on the
OnStateChanged button (highlighted in figure 2) to create a new event handler for this event. Add
the following code to it:
Page 5
Message system
{
list.Items.RemoveAt(i); //drop endpoint from the listview
break;
}
}
}
}
Each active connection can have one of three possible states: Connecting, Connected or
Disconnected. Whenever this state changes, the port will issue the OnStateChanged event. So
basically, when we get an event with the connected state means we have just established a new
connection, in this case we create a new MsgSrvUserState object and assigning it to the UserState
property of the connection which state is being reported. We also add a new item to the ListView
to reflect the new connection.
In the other hand, when we get an event with the disconnected state means a connection we had
previously established is being closed and discarded. In this case, we simply erase the
corresponding row in the ListView. There is no need to do anything about the user state we
previously created since our user state object does not need any cleanup and will be collected; this
however might not always be the case, so you can use this opportunity to do the necessary
cleanup.
Next we need to write a handler for the OnReceiveMessage event. Open the port configuration
again, select the server port and click on the OnReceiveMessage button to create the event
handler. Fill with the code shown below:
Page 6
Message system
Here we parse the received message and process accordingly. If we receive a REGISTER command,
we update the UserState object (and the listview), if we receive a SEND command, we generate a
new message appending the nickname of the user that is sending it and broadcast to all active
connections. Finally if we receive a DISCONNECT command, we simply drop the connection calling
it’s Disconnect method.
Notice we are using two methods named scape and unscape; we previously said we need to do a
scape operation to avoid potential parsing errors, those functions are show below:
The final step would be to write the click event handlers for the start/stop buttons in the form:
Also remember to set the SyncControl property of the Port Manager component to avoid cross-
thread exceptions (figure 3).
Page 7
Message system
However mind the fact that handling all events in the GUI thread might cause the user interface to
hang or appear non-responsive. It’s the same problem you would face if you start doing expensive
processing in the click event handler of a button for instance.
Client application
For our client application, create a new windows application project named
“MessageSystemClient”, and add some components to the main form to match the layout shown
in figure 4.
Page 8
Message system
After that, open the port configuration screen and create a new client port using the Udp
interface. Name this port “MsgSrvClient” and make sure you add the message delimiter as show in
figure 5.
After saving the new port, click on the OnStateChanged button to write the corresponding event
handler. Fill it with the following code:
Page 9
Message system
}
In this event handler we manage the state of the connect and disconnect buttons, also when an
event reports a Connected state, we send the REGISTER command to the server.
Next we write the click event handler for the Send button as follows:
Go back to the Port configuration screen (by right clicking in the Port Manager component and
selecting the Port configuration option from the contextual menu), select the client port and click
on the OnReceiveMessage button to write the corresponding event handler:
Finally we need to write the event handlers for the connect and disconnect buttons. It is important
to note that we cannot know the IP/Port of the server at design time, this information needs to be
provided by the user. When we click the connect button, we need to update the Hostname and
Port properties of the client port before calling the Start method:
On the other hand, when we click the disconnect button, we first send the DISCONNECT command
to the server, and then call the Stop method on the Port Manager:
Page 10
Message system
We also need to set the SyncControl property of the Port Manager control to avoid cross-thread
exceptions here.
Build and run the solution (start both applications), make sure you click the start button in the
server application before you start doing anything with the client. Also note that you can run
several instances of the client and see how a conversation would look.
Note: The complete Visual Studio solution for this example can be found in your installation route
under the examples folder, look for the MessageSystem example.
Page 11