RSS Feed
Download our iPhone app
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 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
                '---connect to server
                client = New TcpClient
                client.Connect("", portNo)
                ReDim data(client.ReceiveBufferSize)
                '---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
            End Try
            '---disconnect from server
            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
    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)
            '---send a message to the server
            Dim ns As NetworkStream = client.GetStream
            Dim data As Byte() = _
            '---send the text---
            ns.Write(data, 0, data.Length)
        Catch ex As Exception
        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)
            Dim bytesRead As Integer
            bytesRead = client.GetStream.EndRead(ar)
            If bytesRead < 1 Then
                Exit Sub
                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)
    End Sub

    Private Sub Form1_FormClosing( _
       ByVal sender As Object, _
       ByVal e As _
          System.Windows.Forms.FormClosingEventArgs) _
       Handles Me.FormClosing
    End Sub
Finally, the Disconnect() subroutine disconnects the client from the server:

    Public Sub Disconnect()
        '---Disconnect from server
        Catch ex As Exception
        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.
Email AuthorEmail Author
Close Icon
Thanks for your registration, follow us on our social networks to keep up-to-date