Browse DevX
Sign up for e-mail newsletters from DevX


Home-brew Your Own Instant Messenger App with Visual Studio .NET : Page 3

Learn .NET network programming by writing your own chat application, and in the process, create a slick client-server application that supports simultaneous conversations with multiple clients.




Building the Right Environment to Support AI, Machine Learning and Deep Learning

Building the Client
Now that the server is built, it is time to build the client. Using Visual Studio 2005, I create a new Windows application (name it WinClient) and populate the default form with the controls shown in Table 1 (see the resulting form in Figure 2).

Table 1. Client Controls

Control(Name) Property Value
Label Text Nick
TextBox Name txtNick
TextBox Name txtMessageHistory
  MultiLine True
  ReadOnly True
TextBox Name txtMessage
Button Name btnSignIn
  Text Sign In
Button Name btnSend
  Text Send

The client application logic is very similar to the server, albeit more straightforward. Double-click on the form to switch to the edit window, and import the following namespace:

Imports System.Net.Sockets

Define the following constant and variables within the form:

Const portNo As Integer = 500 Dim client As TcpClient Dim data() As Byte

Figure 2. Adding Controls: Populate the Windows Form with the various controls from Table 1.
When the user signs in, the client first connects to the server and sends the nickname of the user using the SendMessage() subroutine (defined shortly). Then it should begin reading data from the server asynchronously and change the name of the Sign In button to "Sign Out." When the user signs out from the chat application, you invoke the Disconnect() subroutine (defined shortly).

Private Sub btnSignIn_Click( _ ByVal sender As System.Object, _ ByVal e As System.EventArgs) _ Handles btnSignIn.Click If btnSignIn.Text = "Sign In" Then Try '---connect to server client = New TcpClient client.Connect("", portNo) ReDim data(client.ReceiveBufferSize) SendMessage(txtNick.Text) '---read from server client.GetStream.BeginRead( _ data, 0, _ CInt(client.ReceiveBufferSize), _ AddressOf ReceiveMessage, Nothing) btnSignIn.Text = "Sign Out" btnSend.Enabled = True Catch ex As Exception MsgBox(ex.ToString) End Try Else '---disconnect from server Disconnect() btnSignIn.Text = "Sign In" btnSend.Enabled = False End If End Sub

When the user clicks on the Send button, the application sends a message to the server:

Private Sub btnSend_Click( _ ByVal sender As System.Object, _ ByVal e As System.EventArgs) _ Handles btnSend.Click SendMessage(txtMessage.Text) txtMessage.Clear() End Sub

The SendMessage() subroutine, used in the code above, allows the client to send a message to the server:

Public Sub SendMessage(ByVal message As String) Try '---send a message to the server Dim ns As NetworkStream = client.GetStream Dim data As Byte() = _ System.Text.Encoding.ASCII.GetBytes(message) '---send the text--- ns.Write(data, 0, data.Length) ns.Flush() Catch ex As Exception MsgBox(ex.ToString) End Try End Sub

The ReceiveMessage() subroutine asynchronously reads data sent from the server in a separate thread. When the data is received, it will display the data in the txtMessageHistory control. As Windows controls are not thread-safe, you need to use a delegate, delUpdateHistory(), to update the controls:

Public Sub ReceiveMessage(ByVal ar As IAsyncResult) Try Dim bytesRead As Integer bytesRead = client.GetStream.EndRead(ar) If bytesRead < 1 Then Exit Sub Else Dim para() As Object = _ {System.Text.Encoding.ASCII.GetString( _ data, 0, bytesRead)} Me.Invoke(New delUpdateHistory( _ AddressOf Me.UpdateHistory), para) End If client.GetStream.BeginRead( _ data, 0, CInt(client.ReceiveBufferSize), _ AddressOf ReceiveMessage, Nothing) Catch ex As Exception End Try End Sub

The delUpdateHistory() delegate is used to invoke the UpdateHistory() function in the main thread:

'---delegate and subroutine to update the ' TextBox control Public Delegate Sub delUpdateHistory( _ ByVal str As String) Public Sub UpdateHistory(ByVal str As String) txtMessageHistory.AppendText(str) End Sub Private Sub Form1_FormClosing( _ ByVal sender As Object, _ ByVal e As _ System.Windows.Forms.FormClosingEventArgs) _ Handles Me.FormClosing Disconnect() End Sub

Finally, the Disconnect() subroutine disconnects the client from the server:

Public Sub Disconnect() '---Disconnect from server Try client.GetStream.Close() client.Close() Catch ex As Exception MsgBox(ex.ToString) End Try End Sub

Testing the Application
To test the applications, first run the server by pressing F5 in Visual Studio 2005. You want to launch multiple copies of the client to test the multi-user capabilities of the server. To do this, compile the client-side code files provided with this article into an .exe file. Run multiple copies of Winclient.exe and sign in and chat at the same time.

In this article, I've shown how the TcpClient class allows you to perform asynchronous communication between two computers. While the chat application developed in this article is simple, it is a foundation on which to build more complicated chat applications. In my next article I'll do exactly that, adding FTP, private chats, and more to this simple chat application.

Wei-Meng Lee is a Microsoft .NET MVP and co-founder of Active Developer, a training company specializing in .NET and wireless technologies. He is a frequent speaker and author of numerous books on .NET, XML, and wireless technologies.
Thanks for your registration, follow us on our social networks to keep up-to-date