C# Chat Application Over Asynchronous UDP Sockets – Part 2, The Client

by Dave on August 5, 2009

in Articles,Internet

Chat ClientIn this article I will be showing you how to create a client for our chat application. This is part two of the series, so if you haven’t read part one yet please do so before continuing with this article as it explains the infrastructure of the whole application. You can read part one here: C# Chat Application Over Asynchronous UDP Sockets – Part 1, The Server.

The Client

For our client to connect to the server, which is listening for incoming connections, the server must obviously be running :) . Apart from that, the client must know the IP address of the server and which port the server is listening on. We already know from part one of this article series that the server is listening on port 30,000. However we don’t know the server’s IP address so that will have to be input manually from the user interface of the client.

The client will make use of the exact same Packet class we used for the server. In fact this class could have been placed into a library and included into each project as a dll instead of replicating the code twice… but it makes no difference for the purpose of this example, plus I didn’t feel like creating a dll :) .

Anyway, our client looks something like this:

Chat Client

As can be seen in the above screenshot, there is a section where the user must input a user name and a server IP address. Once this is done the user must click the connect button to let the server know that a client is connecting. The connect code is shown below:

private void btnConnect_Click(object sender, EventArgs e)
{
    try
    {
        this.name = txtName.Text.Trim();

        // Initialise a packet object to store the data to be sent
        Packet sendData = new Packet();
        sendData.ChatName = this.name;
        sendData.ChatMessage = null;
        sendData.ChatDataIdentifier = DataIdentifier.LogIn;

        // Initialise socket
        this.clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);

        // Initialise server IP
        IPAddress serverIP = IPAddress.Parse(txtServerIP.Text);

        // Initialise the IPEndPoint for the server and use port 30000
        IPEndPoint server = new IPEndPoint(serverIP, 30000);

        // Initialise the EndPoint for the server
        epServer = (EndPoint)server;

        // Get packet as byte array
        byte[] data = sendData.GetDataStream();

        // Send data to server
        clientSocket.BeginSendTo(data, 0, data.Length, SocketFlags.None, epServer, new AsyncCallback(this.SendData), null);

        // Initialise data stream
        this.dataStream = new byte[1024];

        // Begin listening for broadcasts
        clientSocket.BeginReceiveFrom(this.dataStream, 0, this.dataStream.Length, SocketFlags.None, ref epServer, new AsyncCallback(this.ReceiveData), null);
    }
    catch (Exception ex)
    {
        MessageBox.Show("Connection Error: " + ex.Message, "UDP Client", MessageBoxButtons.OK, MessageBoxIcon.Error);
    }
}

In the above code, the first thing we are doing is creating a Packet object and setting the data identifier to LogIn. When this packet is sent it will let the server know that a client wants to join the chat room. Next we are initialising the server and socket details and then the Packet is converted into a byte array and sent to the server. Finally the client starts listening for any broadcasts from the server and when it receives something the received data is processed with the below code:

private void ReceiveData(IAsyncResult ar)
{
    try
    {
        // Receive all data
        this.clientSocket.EndReceive(ar);

        // Initialise a packet object to store the received data
        Packet receivedData = new Packet(this.dataStream);

        // Update display through a delegate
        if (receivedData.ChatMessage != null)
            this.Invoke(this.displayMessageDelegate, new object[] { receivedData.ChatMessage });

        // Reset data stream
        this.dataStream = new byte[1024];

        // Continue listening for broadcasts
        clientSocket.BeginReceiveFrom(this.dataStream, 0, this.dataStream.Length, SocketFlags.None, ref epServer, new AsyncCallback(this.ReceiveData), null);
    }
    catch (ObjectDisposedException)
    {}
    catch (Exception ex)
    {
        MessageBox.Show("Receive Data: " + ex.Message, "UDP Client", MessageBoxButtons.OK, MessageBoxIcon.Error);
    }
}

The above code is very simple. Since the client can only receive a Message from the server there is no need to process the data identifier which is at the beginning of the packet. Obviously, if you want your code to be robust and capable of handling any type of exception, you should check the data identifier… just in case.

All the code in this article can be made more robust. For example, there is no check to validate the IP address entered by the user in the client UI. There are no limits to the lengths of the input fields in the UI. There is no verification that the whole packet has in fact arrived in tact and uncorrupted. I think you get the picture… there is never a limit to the amount of checks you can perform and every good developer adds at least some of these checks to make the application more robust.

Conclusion

As you can see creating a client-server chat application using UDP is not that difficult. Obviously, there are many improvements you could make to this application. For example:

  • assign a different colour to different users so as to easily identify them apart,
  • allow sending of files (this would require a change to the custom data packet, and it would be better to use TCP instead of UDP for sending files,
  • display a list of all connected users on every client UI,
  • convert the server into a Windows Service to avoid starting it up manually,
  • add support for emotions,
  • implement a system to differentiate between users with the same name,
  • etc.

I really hope you enjoyed this article. Please leave your comments below and don’t forget to download the whole code listing from below – it requires Microsoft Visual Studio 2008.

Also, if you haven’t already subscribed to my rss feed, please do so – Grab RSS Feed. And if you like you can also follow me on Twitter.

Dave

Download sourceDownload Chat Client source – 15.0 KB
Download Chat Server source – 14.8 KB



Leave a Comment

Previous post:

Next post: