Ошибка при принятии данных (строки) сервером

Ув. программисты, подскажите, пожалуйста, как решить проблему.
Принимаю от клиента текстовую строку:

stream = client.GetStream();
byte[] data = new byte[64]; // буфер для получаемых данных
List<byte> list = new List<byte>(); // Большой buffer
while (true)
{
 // получаем сообщение
  //  StringBuilder builder = new StringBuilder();
  int bytes = 0;
  do
  {
    bytes = stream.Read(data, 0, data.Length);
   //  builder.Append(Encoding.UTF8.GetString(data, 0, bytes));
                        list.AddRange(data.Take(bytes));
   }
   while (stream.DataAvailable);
 
   string message = Encoding.UTF8.GetString(list.ToArray(), 0, list.Count);

Но при получение большой строки (1700 байт например) строка режется (вот этим символом �).
Если увеличить вместимость массива data больше чем байтов в строке (например, с 64 на 2048 байт), то все работает норм.
Подскажите, пожалуйста, почему это происходит и как это исправить, ибо строки иногда могут быть и длиннее…

Заранее большое спасибо!!!

Режется где?

Вообще в любой непонятной ситуации надо использовать отладчик или отладочный вывод.

Например, сравнить содержимое list в этих двух ситуациях.

В том то и дело, что я не могу понять…
Не вижу связи и логики, где может все оборваться…
Когда присылаю данные, например в 500 байт - все работает четко…
Насчет, отладки… Когда я включаю отладку и построчно пробегаю по коду вручную (а именно по циклу), то есть до “string message”, то все работает, как ни странно… Никаких ошибок не вылетает и в переменную в итоге пишутся все данные.
Кстати, не дописал в предыдущем посте: ошибка вылетает “Индекс находился вне границ массива”.

тогда:

выведите байты из list в файл, посмотрите hex-редактором.

Где?

Я просто новичок… как это сделать…
Как посмотреть list в hex редакторе…
И где можно посмотреть, где именно ошибка вылетает? Просто программа не прекращает свою работу, как при обычной ошибке, где Студия показывает строку проблемную… У меня это сообщение вылетает в консоле (Само приложение консольное), так как вышеуказанный код обернут в Ловушку ошибок (КетчЭкспешн)… Может убрать его? И оставить чисто этот код? Посмотреть, что покажет Студия?

File.WriteAllBytes("myfile.bin", list.ToArray()); и чтобы увидеть его в виде байтов скачать любой хекс-редактор, например, https://mh-nexus.de/en/hxd/

Так там и выведите куда угодно информацию об исключении.

using System;
					
public class Program
{
	public static void badFunction()
	{
		throw new Exception("BOOM");
	}
	
	public static void Main()
	{
		try
		{
		    badFunction();
		}
		catch (Exception ex)
		{
		    Console.WriteLine(ex.ToString());
		}
	}
}

Я сделал, как вы сказали… И нашел строчку, которая вызвает ошибку, но она вроде не имеет отношения к проблемы. Дело в том, что после получения переменной message я ее делю через сплит и части ее помещаю в массив, а потом передаю ее части для дальнейшей работы в другую функцию… И так как строка приходит не полностью, но не всех параметров хватает, поэтому и вылетает ошибка, как я понял… Но ведь проблема не исчезла. Строка пришла не полностью.
Посмотрел данные в HEX редакторе… Тоже самое. В файле данные строки не полностью содержатся.
Вот выслал весь код этой функции.

public void Process()
        {
            NetworkStream stream = null;
            try
            {
                stream = client.GetStream();
                byte[] data = new byte[64]; // буфер для получаемых данных
                List<byte> list = new List<byte>(); // Большой buffer
                while (true) 
                {
                    // получаем сообщение
                    //  StringBuilder builder = new StringBuilder();
                    int bytes = 0;
                    do
                    {
                        bytes = stream.Read(data, 0, data.Length);
                        ///  builder.Append(Encoding.UTF8.GetString(data, 0, bytes));
                        list.AddRange(data.Take(bytes));
                    }
                    while (stream.DataAvailable);

                    string message = Encoding.UTF8.GetString(list.ToArray(), 0, list.Count) /* builder.ToString() */;

                    System.IO.File.WriteAllBytes("myfile.bin", list.ToArray());

                    Console.WriteLine(message);

                    String[] strArr = null;                    
                    
                    char[] splitchar = { '&' };
                    strArr = message.Split(splitchar);                    

                    if (strArr[0] == "VHOD")
                    {
                        String otvet = Enter(strArr[1], strArr[2]); //Здесь ошибка                        
                        data = Encoding.UTF8.GetBytes(otvet);
                        stream.Write(data, 0, data.Length);
                    }                 
                    stream.Close();
                    client.Close();
                    // отправляем обратно сообщение 
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
                stream.Close();
                client.Close();
            }
            finally
            {
                if (stream != null)
                    stream.Close();
                if (client != null)
                    client.Close();
            }
        }

Напечатайте или вставьте сюда код

Я не могу понять, почему при ручной отладке все работает… когда я медленно построчно прохожу код. Такое ощущение, что эта процедура выполняется быстрее, чем данные до нее доходят, и соответственно она принимает не всю строку. С другой стороны, ведь while (stream.DataAvailable); должна обеспечивать обработку данных пока они не закончатся?

Ну так если тут в файле не все данные, а например при прохождении по шагам в отладчике всё работает, то несложно догадаться о причинах )

Скорее всего чтение происходит быстрее, чем приходят данные, и stream.DataAvailable временно становится false.

Надо по-другому протокол и чтение организовывать.
Например, в самом начале прислать длину сообщения, и потом пытаться читать пока не прочитается столько.

https://stackoverflow.com/a/9088533/964478


проще с using

2 лайка

Вроде сделал. Отправляю в первой порции данных, первыми 6 байтами размер всего того, что будет в строке после. А DataAvaible заменил на количество байтов в строке (не считая байтов, определяющих размер строки после них) и кручу циклю пока размер Списка не станет таким же, как и количество байт, которые должны прийти. Таким методом я все получаю… Пробовал даже очень большие строки отправлять - все доходит. Надеюсь в этой схеме нет подводных камней.)))) Спасибо за совет!))))