views:

58

answers:

1

Hello,

I have a simple class that handles the connection being made between a client and server.

To let more than one user communicate with the server at one time each new Client connection is made on a separate thread.

In this class I create two streams that act as the inbound and outbound streams for the client. I create the fields first and then initialise the object in a separate method, simply because the object is used in several other places.

I've come to the point where I want to refactor the code to make it more robust, my first port of call was memory management. I've come to love the using() statement but noticed that I can't really see a way to do implement it due to the way the code is structured. This means I have a fairly annoying method that is just used for closing the underlying connections and nothing more.

Furthermore, I came to implement exception handling and was curious whether the notion of wrapping the entire code in a method with a try{} statement and then having sequential catch() blocks with the applicable exception types was the best idea.

I hope I explained myself correctly, I'll post a snippet for you to look at.

Thanks!

//Fields
        TcpClient tcpClient;

        //The thread that will send information to the client
        private Thread thrSender;
        private StreamReader srReceiver;
        private StreamWriter swSender;
        private string currentUser;
        private string strResponse;

        //The constructor of the class takes in a TCP connection
        public Connection(TcpClient tcpCon)
        {
            tcpClient = tcpCon;

            //The thread that accepts the client and waits messages
            thrSender = new Thread(AcceptClient);

            //The thread calls the AcceptClient method
            thrSender.Start();
        }

        private void CloseConnection()
        {
            //Close the currently open objects
            tcpClient.Close();
            srReceiver.Close();
            swSender.Close();
        }

        //Occurs when a new client is accepted
        private void AcceptClient()
        {
            srReceiver = new StreamReader(tcpClient.GetStream());
            swSender = new StreamWriter(tcpClient.GetStream());

            //Read account information from the client
            currentUser = srReceiver.ReadLine();

            //Examine response from client
            if (currentUser != "")
            {
                //Store the user name in the hash table
                if (ChatServer.htUsers.Contains(currentUser) == true)
                {
                    //0 means not connected - Writes error to Client and Server log
                    swSender.WriteLine("0|This username already exists.");
                    swSender.Flush();
                    CloseConnection();
                    return;
                }
                //More if/else if/else statements
                //...  

        }

    }
+1  A: 

You can dispose of the two streams fairly easily within the AcceptClient method by making them local variables since they aren't referenced elsewhere something like this:

private void AcceptClient()
{
    using (StreamReader srReceiver = new StreamReader(tcpClient.GetStream()))
    {
        using (StreamWriter swSender = new StreamWriter(tcpClient.GetStream()))
        {
            // ...
        }
    }
}

The tcpClient is more tricky because it is being created on one thread and cleaned up on another. Unless you can change that then perhaps the best option is going to be to implement the cleanup within a try/finally.

private void AcceptClient()
{
    try
    {
        using (StreamReader srReceiver = new StreamReader(tcpClient.GetStream()))
        {
            using (StreamWriter swSender = new StreamWriter(tcpClient.GetStream()))
            {
                // ...
            }
        }
    }
    finally
    {
        tcpClient.Dispose();
    }
}

The finally clause will get called whether or not the try clause throws an exception.

Steve
Excellent, thanks!
Jamie Keeling
You're welcome!
Steve