A few points to discuss
In this simple project, I have made use of only a few namespaces:
System.Windows.Forms;
System.Net.Sockets;
System.Threading;
System.Timers;
I found that these namespaces really make the project much simpler than it
would have been if it is done in C++. In addition, the delegate concept also
makes the event-driven model much easier to handle than C++.
Most of the program flow and techniques used are already documented inside
the code as comments. However, there are a few points that I think will be worth
discussing here.
First of all, I think the System.Net.Sockets provides a lot of great classes
that make the Socket programming a joy to work with, especially the TcpListener,
TcpClient and UdpClient classes. They take care of most of the low-level socket
programming under the hood and make their operation transparent to the client
code. For example, to create a TCP server and make it listen to the port TCP_PORT,
all I have to do is only 1 line of code:
TcpListener tcpListener = new TcpListener(TCP_PORT).
And to create a TCP client and make a connection to the TCP server SERVER_NAME
at TCP_PORT, again, 1 line of code will do the job:
TcpClient tcpClient = new TcpClient(SERVER_NAME, TCP_PORT).
Although all these classes still perform the traditional socket operations
under the hood, hiding all of them from the client application does help simplify
the overall program structure. However, for those programmers who are familiar
with Winsock programming, I still suggest to use the traditional Socket class
because it's still more powerful then these "convenient" siblings.
Second, this project has made use of the Multi-Threading facilities provided
by the .NET platform. The UDP server and the TCP server are running on different
threads so that they can receive and process incoming messages simultaneously.
The following code segments show how the TCP and UDP threads can be started and
aborted:
public void start_servers()
{
//Starting the TCP Listener thread (StartListen).
sampleTcpThread = new Thread(new
ThreadStart(this.StartListen));
sampleTcpThread.Start();
//Starting the UDP Notify thread (receiveNotify).
udpNotifyThread = new Thread(new
ThreadStart(this.receiveNotify));
udpNotifyThread.Start();
}
To start the server threads:
start_servers();
To abort them:
sampleTcpThread.Abort();
udpNotifyThread.Abort();
This is it! Of course, you might want to add some try/catch blocks to handle
some exceptions that might happen in the codes.
The third thing that I want to discuss is the delegate model of event handling.
In this project, there are quite a few places that I can make use of delegates.
For example, in Fig 1, step 6, after the calling side connects to the called
side's TcpUdpServer, the TcpUdpServer will raise an event. The event will then
call the delegate defined in the WinChatFormLibrary class, which will, through
the TcpUdpClient, make a connection to the calling side's TcpUdpServer. Here
is the code segment that does what I described.
In WinChatFormLibrary class, we first have to make the TcpUdpServer listen
to the event peerNotify():
TcpUdpServer.peerNotify += new
TcpUdpServer.NotificationHandler(this.OnPeerNotify);
Defining the OnPeerNotify delegate (with most details deleted):
public void OnPeerNotify()
{
this.tcpUdpClient.createTcpClientConnection(remoteHostName};
}
In the TcpUdpServer, all we have to do is to call the event peerNotify() when
it receives a connection from the remote peer. And it's done!
Last but not least, I also want to briefly mention the timer handling in the
.NET platform. I have made use of a few timers in this project. To start a timer,
all I have to do is just 2 steps:
1. Add the event listener to the code where you want to start the timer:
receiveNotifyTimer = new
System.Timers.Timer(30000);
receiveNotifyTimer.Elapsed += new
ElapsedEventHandler(this.OnTimedEvent);
2. Define the delegate OnTimeEvent():
public void OnTimedEvent1(object source, ElapsedEventArgs e)
{
//Do something when the timer expires.
}
And stopping a timer is just a matter of calling someTimer.Stop().
That's it!!