Login | Register   
RSS Feed
Download our iPhone app
Browse DevX
Sign up for e-mail newsletters from DevX

By submitting your information, you agree that devx.com may send you DevX offers via email, phone and text message, as well as email offers about other products and services that DevX believes may be of interest to you. DevX will process your information in accordance with the Quinstreet Privacy Policy.


Extend Your Instant Messenger Application with FTP Support and Private Chat : Page 3

In part 1 of this article, you learned to create a mult-user chat application using network programming in .NET. In this article, you'll build on that application to add sophisticated features such as file downloads.




Application Security Testing: An Integral Part of DevOps

Building the Server
There are two components in this chat application: server and client. For the server, I will create a console application project using Visual Studio 2005 beta 2. Name the project "Server."

Editor's Note: While we originally reported this project as suitable for Visual Studio 2003, we have learned that one line of code causes a problem in that version. We regret the error.

In the default Module1.vb, populate it with the following:

Imports System.Net.Sockets Module Module1 Const portNo As Integer = 500 Dim localAdd As System.Net.IPAddress = _ System.Net.IPAddress.Parse("") Dim listener As New _ System.Net.Sockets.TcpListener(localAdd, portNo) Sub Main() listener.Start() While True Dim user As New _ ChatClient(listener.AcceptTcpClient) End While End Sub End Module

The next step is to define the ChatClient class. The ChatClient class is used to represent information from each client connecting to the server. Add a new Class to your project in Visual Studio 2005 and name it ChatClient.vb.

First, import the following namespace:

Imports System.Net.Sockets

In the ChatClient class, first define the various private members (their uses are described in the comments in the code). You also declare a HashTable object (AllClients) to store a list of all clients connecting to the server. The reason for declaring it as a shared member is to ensure all instances of the ChatClient class are able to obtain a list of all the clients currently connected to the server:

'---class to contain information of each client Public Class ChatClient '---contains a list of all the clients Public Shared AllClients As New Hashtable '---information about the client Private _client As TcpClient Private _clientIP As String Private _ClientNick As String '---used for sending/receiving data Private data() As Byte

When a client gets connected to the server, the server will create an instance of the ChatClient class and then pass the TcpClient variable (client) to the constructor of the class. You will also get the IP address of the client and use it as an index to identify the client in the HashTable object. The BeginRead() method will begin an asynchronous read from the NetworkStream object (_client.GetStream) in a separate thread. This allows the server to remain responsive and continue accepting new connections from other clients. When the reading is complete, control will be transferred to the ReceiveMessage() function (which I will define shortly).

'---when a client is connected Public Sub New(ByVal client As TcpClient) _client = client '---get the client IP address _clientIP = client.Client.RemoteEndPoint.ToString '---add the current client to the hash table AllClients.Add(_clientIP, Me) '---start reading data from the client in a ' separate thread ReDim data(_client.ReceiveBufferSize - 1) _client.GetStream.BeginRead(data, 0, _ CInt(_client.ReceiveBufferSize), _ AddressOf ReceiveMessage, Nothing) End Sub

In the ReceiveMessage() function, I first call the EndRead() method to handle the end of an asynchronous read. Here, I check if the number of bytes read is less then 1. If it is, the client has disconnected and you need to remove the client from the HashTable object (using the IP address of the client as an index into the hash table). I also want to broadcast a message to all the clients telling them that this particular client has left the chat. I do this using the Broadcast() function (again, I will define this shortly).

In this function, you check the various message formats sent from the client and take the appropriate action. For example, if the client initiates a FTP request, you need to repackage the message (as described in the earlier section "Protocol Description") and send it to the recipient. Listing 1 shows the full code for the ReceiveMessage() function.

The SendMessage() function allows the server to send a message to the client.

'---send the message to the client Public Sub SendMessage(ByVal message As String) Try '---send the text Dim ns As System.Net.Sockets.NetworkStream SyncLock _client.GetStream ns = _client.GetStream Dim bytesToSend As Byte() = _ System.Text.Encoding. _ ASCII.GetBytes(message) _ ns.Write(bytesToSend, 0, _ bytesToSend.Length) ns.Flush() End SyncLock Catch ex As Exception Console.WriteLine(ex.ToString) End Try End Sub

Finally, the Broadcast() function sends a message to all the clients stored in the AllClients HashTable object.

'---broadcast message to selected users Public Sub Broadcast(ByVal message As String, _ ByVal users() As String) If users Is Nothing Then '---broadcasting to everyone Dim c As DictionaryEntry For Each c In AllClients '---broadcast message to all users CType(c.Value, _ ChatClient).SendMessage(message & vbCrLf) Next Else '---broadcasting to selected ones Dim c As DictionaryEntry For Each c In AllClients Dim user As String For Each user In users If CType(c.Value, ChatClient). _ _ClientNick = user Then '---send message to user CType(c.Value, ChatClient). _ SendMessage(message & vbCrLf) '---log it locally Console.WriteLine("sending -----> " _ & message) Exit For End If Next Next End If End Sub

Comment and Contribute






(Maximum characters: 1200). You have 1200 characters left.



Thanks for your registration, follow us on our social networks to keep up-to-date