内存管理和异常处理

发布于 2024-09-28 08:48:59 字数 2230 浏览 0 评论 0原文

我有一个简单的类来处理客户端和服务器之间的连接。

为了让多个用户同时与服务器通信,每个新的客户端连接都在单独的线程上建立。

在此类中,我创建两个流,充当客户端的入站流和出站流。我首先创建字段,然后在单独的方法中初始化对象,只是因为该对象在其他几个地方使用。

我已经到了想要重构代码以使其更加健壮的地步,我的第一个调用端口是内存管理。我开始喜欢 using() 语句,但注意到由于代码的结构方式,我无法真正找到实现它的方法。 这意味着我有一个相当烦人的方法,它仅用于关闭底层连接,仅此而已。

此外,我开始实现异常处理,并且很好奇将整个代码包装在带有 try{} 语句的方法中,然后使用具有适用异常类型的连续 catch() 块的想法是否是最好的主意。

我希望我的解释是正确的,我将发布一个片段供您查看。

谢谢!

//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
                //...  

        }

    }

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
                //...  

        }

    }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

江心雾 2024-10-05 08:48:59

您可以在 AcceptClient 方法中相当轻松地处理这两个流,方法是将它们设置为局部变量,因为它们不会在其他地方引用,如下所示:

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

tcpClient 更棘手,因为它是在一个线程上创建并在另一个线程上清理的。除非你可以改变这一点,否则最好的选择可能是在 try/finally 中实现清理。

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

无论 try 子句是否抛出异常,finally 子句都会被调用。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文