C # TcpClient и NetworkStream для отправки / получения данных по TCP.Почему бы не использовать блок «using» и я могу читать данные сразу после записи в поток? - PullRequest
0 голосов
/ 20 февраля 2019

Я читаю документацию по использованию TcpClient и NetworkStream для записи и чтения из потока подключения Tcp.Но я замечаю, что вся документация Microsoft не использует блок «using», хотя даже TcpClient и NetworkStream реализуют IDisposable.

Итак, мне было интересно, почему это так.

Я также заметил в нескольких примерахчто они пишут в поток , а затем сразу после читают из потока.Это не правильно, но я новичок в сети, но я написал что-то вроде приведенного ниже кода, чтобы сделать именно это.

Хотя код работает, я не уверен, насколько он хорош и надежен.В частности, если данные недоступны для чтения, как только я проверю их, выполнение будет продолжено.В этот момент данные могут быть доступны для чтения, но тогда уже поздно, я уже прошел этот пункт.

Мои вопросы пишутся с заглавной буквы в виде комментариев кода ниже

using (TcpClient client = new TcpClient())  // WHY NOT USING?
{
    client.Connect(ip, port);

    using (NetworkStream stream = client.GetStream())  // WHY NOT USING?
    {
        byte[] messageBytes = ...;
        if (stream.CanWrite)
        {
            await stream.WriteAsync(messageBytes, 0, messageBytes.Length);
            stream.Flush();
        }

        // IS THIS DATA GOING TO BE AVAILABLE AT THIS POINT?  
        // IF NOT, THEN YOU WILL HAVE NO OPPORTUNITY TO READ DATA 
        // SINCE NOTHING IS GOING TO TELL YOU WHEN IT IS GOING TO BE AVAILABLE.  
        // BY THE TIME IT IS AVAILABLE, THE EXECUTION MAY PASS THIS POINT, WHAT THEN???
        if (stream.CanRead)  
        {
            byte[] buffer = newe byte[1024];
            int readSoFar = 0;
            StringBuilder builder = new StringBuilder();

            while(stream.DataAwailable)
            {
                readSoFar = await stream.ReadAsync(buffer, 0, buffer.Length);
                builder.AppendFormat("{0}", Encoding.ASCII.GetString(buffer, 0, readSoFar));
            }

            string msg = builder.ToString();
        }
    }
}

1 Ответ

0 голосов
/ 20 февраля 2019

TcpClient / NetworkStream / Socket имеют только один неуправляемый ресурс под капотом.Это сама розетка.Ваш код может иметь только 1, используя блок, и вы будете в порядке.В вашем примере, когда код покидает блок using (NetworkStream), он закрывает базовый сокет, а TcpClient.Dispose фактически ничего не делает.

О Read / ReadAsync.Данные не доступны сразу.Но эти методы ждут одного из 2 событий: данные появляются на сокете, или другая сторона закрывает tcp сокет.Как только в сокете появляется 1 байт, эти функции немедленно возвращают результат.Если другая сторона закрывает соединение, эти функции возвращают 0, что фактически указывает на завершение потока.

Обычно не следует использовать свойство DataAvailable.В вашем примере это может привести к неожиданному поведению.Вы можете просто использовать Read / ReadAsync, пока они не вернут ноль.

...