Вопрос

Просто я пытался реализовать то, что BufferedStreamReader делает на Java.У меня открыт поток сокетов, и я просто хочу прочитать его в построчно-ориентированном виде - построчно.

У меня есть следующий серверный код.

while (continueProcess)
        {
            try
            {
                StreamReader reader = new StreamReader(Socket.GetStream(), Encoding.UTF8);
                string command = reader.ReadLine();
                if (command == null)
                    break;

                OnClientExecute(command);
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
        }

И следующий клиентский код:

TcpClient tcpClient = new TcpClient();
        try
        {
            tcpClient.Connect("localhost", serverPort);
            StreamWriter writer = new StreamWriter(tcpClient.GetStream(), Encoding.UTF8);
            writer.AutoFlush = true;
            writer.WriteLine("login>user,pass");
            writer.WriteLine("print>param1,param2,param3");
        }
        catch (Exception e)
        {
            Console.WriteLine(e.ToString());
        }
        finally
        {
            tcpClient.Close();
        }

Сервер считывает только самую первую строку (login>user,pass) и затем ReadLine возвращает значение null!

Каков самый простой способ достижения этого линейно-ориентированного читателя, как это есть в Java BufferedStreamReader?:s

Это было полезно?

Решение

Типичный читатель строк - это что-то вроде:

using(StreamReader reader = new StreamReader(Socket.GetStream(), Encoding.UTF8)) {
    string line;
    while((line = reader.ReadLine()) != null) {
        // do something with line
    }
}

(обратите внимание на using чтобы гарантировать, что мы Dispose() это даже если мы получим ошибку, и цикл)

Если вы хотите, вы могли бы абстрагировать это (разделение проблем) с помощью блока итератора:

static IEnumerable<string> ReadLines(Stream source, Encoding encoding) {
    using(StreamReader reader = new StreamReader(source, encoding)) {
        string line;
        while((line = reader.ReadLine()) != null) {
            yield return line;
        }
    }
}

(обратите внимание, что мы переместили это в функцию и удалили "do something", заменив его на "yield return" , который создает итератор (лениво повторяющийся конечный автомат без буферизации)

Затем мы бы потребляли это так же просто, как:

foreach(string line in ReadLines(Socket.GetStream(), Encoding.UTF8)) {
    // do something with line
}

Теперь нашему коду обработки не нужно беспокоиться о как читать строки - просто данный последовательность строк, сделайте с ними что-нибудь.

Обратите внимание, что using (Dispose()) применяется к TcpClient слишком;вам следует завести привычку проверять наличие IDisposable;например (все еще включая ваше протоколирование ошибок):

using(TcpClient tcpClient = new TcpClient()) {
    try {
       tcpClient.Connect("localhost", serverPort);
       StreamWriter writer = new StreamWriter(tcpClient.GetStream(), Encoding.UTF8);
       writer.AutoFlush = true;
       writer.WriteLine("login>user,pass");
       writer.WriteLine("print>param1,param2,param3");
    } catch (Exception ex) {
        Console.Error.WriteLine(ex.ToString());
    }
}

Другие советы

Параметр while в коде вашего сервера настроен на чтение только одной строки для каждого соединения.Вам понадобится еще одно время в течение попытки, чтобы прочитать все отправляемые строки.Я думаю, как только этот поток будет настроен на стороне клиента, он отправит все данные.Затем на стороне сервера ваш поток фактически считывает только одну строку из этого конкретного потока.

Попробовал это и получил

Не удалось найти тип или имя пространства имен 'Stream' (вам не хватает директивы using или ссылки на сборку?) Не удалось найти тип или имя пространства имен 'StreamReader' (вам не хватает директивы using или ссылки на сборку?) Не удалось найти тип или имя пространства имен 'StreamReader' (вам не хватает директивы using или ссылки на сборку?) 'System.Net.Sockets.Сокет' не содержит определения для 'GetStream'

    public string READS()
    {
        byte[] buf = new byte[CLI.Available];//set buffer
        CLI.Receive(buf);//read bytes from stream
        string line = UTF8Encoding.UTF8.GetString(buf);//get string from bytes
        return line;//return string from bytes
    }
    public void WRITES(string text)
    {
        byte[] buf = UTF8Encoding.UTF8.GetBytes(text);//get bytes of text
        CLI.Send(buf);//send bytes
    }

CLI - это сокет.в какой-то новой зоне класс TcpClient больше не работает на моем компьютере, но класс Socket работает просто отлично.

UTF-8 - это многожильная кодировка StreamReader / Writer

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top