Когда мне нужно располагать (сервер-клиент) объекты? - PullRequest
0 голосов
/ 21 марта 2012

в сервере - (мульти) клиентское приложение [TCP]. Я использую Socket, NetworkStream, StreamReader и StreamWriter для каждого клиента, которого я принимаю на сервере ... поэтому у меня есть пара вопросов:

Должен ли я утилизировать их все, когда я хочу закрыть соединение с клиентом? Если клиент располагает сокетом, который подключен к серверу. Должен ли я также располагать сокетом на стороне сервера, или он автоматически закрывается? в моем коде здесь:
 Thread thAccept = new Thread(acceptClient);
 Thread thJob;
 private void acceptClient()
    {
        while (true)
        {
            Socket client = server.Accept();
            Console.WriteLine(client.RemoteEndPoint+" has connected");
            StreamReader reader = new StreamReader(new NetworkStream(client));
            //is it ok to create an instance NetworkStream like this or i will have to dispose it later?

            thJob = new Thread(Job);
            thJob.Start(reader);
        }
    }

 private void Job(object o)
    {
        StreamReader reader = (Socket)o;
        try
        {
            string cmd = null;
            while ((cmd = reader.ReadLine()) != null)
            {
              //(BLA BLA..)
            }
        }
        catch
        {
            Console.WriteLine("Disconnected by catch");  
        }
        finally
        { 
            Console.WriteLine("Finally Done.");
            reader.Dispose();
        }
    }

Этот код подходит для удаления всех (необходимых для удаления) объектов?

1 Ответ

0 голосов
/ 21 марта 2012

Это не дубликат.

Ваш код отличается от связанного дубликата, поскольку в вашем коде IDisposable передается другому потоку.

Общее правило заключается в том, что если вы создаете объект, который реализует IDisposable, то вы отвечаете за вызов Dispose для него, когда закончите с ним. По возможности это следует делать в блоке using, чтобы всегда вызывать Dispose. В вашем случае ваш код не завершен с объектом, пока не завершится другой поток. В этом потоке вы правильно вызываете Dispose в блоке finally.

Если бы вы позвонили Dispose на NetworkStream, то он бы тоже закрыл StreamReader, что бы победило вашу цель. Я подозреваю, что было бы то же самое, если бы вы позвонили Dispose на Socket. Таким образом, ваш код правильный, как есть.

Объект на стороне клиента не имеет отношения к объекту на стороне сервера, кроме как через TCP / IP. Тот факт, что клиент может вызвать Dispose на своем сокете, не означает, что сервер должен вызвать Dispose на своем сокете. Однако, как только сервер завершит чтение данных из сокета и соединение будет закрыто, сокет на стороне сервера должен иметь значение Disposed. Я не знаю наверняка, но я полагаю, что при удалении StreamReader базовый NetworkStream будет удален, что должно вызвать Dispose в сокете, из которого был создан поток.

Ваш код в порядке, за исключением некоторых не связанных проблем: вам не нужно устанавливать cmd в null, так как вы собираетесь установить значение в следующем операторе. Кроме того, вы не должны использовать пустой блок catch как этот. Вы не представляете, какое исключение было сгенерировано, но вы все равно будете его игнорировать, даже не регистрируя и не отображая исключение. По крайней мере, вы должны сделать

    catch (Exception ex)
    {

        Console.WriteLine("Disconnected by exception " + ex.ToString());   
    } 
    finally 
    {  
        Console.WriteLine("Finally Done."); 
        reader.Dispose(); 
    } 
...