C# TcpClient читает или получает неполные данные из потока - PullRequest
0 голосов
/ 07 февраля 2020

У меня есть exe, который имитирует видео поток. Я подключаюсь к нему и очень редко читаю ожидаемые данные, но обычно получаю только первые 28 байтов, а затем 65508 байтов нулей. Предположим, видео поток работает правильно.

TcpClient tcpClient = new TcpClient ();

int port = 13000;
myIP = IPAddress.Loopback.ToString();

tcpClient.Connect (myIP, port);
NetworkStream netStream = tcpClient.GetStream ();

byte[] bytes = new byte[tcpClient.ReceiveBufferSize];

netStream.Read (bytes, 0, (int)tcpClient.ReceiveBufferSize);

string dataString = Encoding.ASCII.GetString (bytes);

Console.WriteLine("\ndataString: "+dataString.Substring(0,1000));
Console.WriteLine("\nnumber of bytes read: "+bytes.Length); 

tcpClient.Close ();
// Closing the tcpClient instance does not close the network stream.
netStream.Close();

Как сделать так, чтобы я каждый раз получал ожидаемый результат?

1 Ответ

0 голосов
/ 07 февраля 2020

TCP представляет собой (двунаправленный) поток данных. Вы должны продолжать читать из него в al oop и анализировать данные по мере необходимости. Он не имеет понятия сообщений - десять записей на одной стороне могут привести к одному чтению на другой стороне так же легко, как одна запись на одной стороне может привести к десяти чтениям на другой стороне.

У вас есть контракт с TCP следующим образом:

  • Если в буфере приема есть данные, Read немедленно возвращается, заполняя предоставленный вами буфер таким количеством данных, сколько доступно, вплоть до длины буфера. Число прочитанных байтов является возвращаемым значением Read.
  • Если в приемном буфере нет данных, Read будет блокироваться, пока не будет хотя бы одного байта данных. Затем следует, как в первом случае.
  • Если другие стороны выключат сокет, Read вернет ноль.

Итак, чтобы заставить работать TCP, вам нужно все oop. Как именно вы сформируете l oop, зависит от того, что вы пытаетесь сделать. Если вы действительно работаете с данными, которые логически представляют собой поток (например, аудиоданные), просто продолжайте читать как можно быстрее и обрабатывайте любые данные, которые вы получаете, по мере их поступления. Если вам нужно отправлять сообщения, вам необходимо реализовать протокол сообщений. Если вам нужно одноразовое сообщение, вы можете просто продолжить чтение, пока Read не вернет ноль.

Ваш случай может быть обработан при первом подходе - продолжайте чтение, пока поток не закроется, и pu sh полученные данные переслать. Предполагая, что данные на самом деле являются потоком текста UTF8, получатель basi c будет выглядеть примерно так:

using (var client = new TcpClient())
{
  tcpClient.Connect(myIP, port);

  var stream = client.GetStream();
  var buffer = new byte[4096]; // Adapt the size based on what you want to do with the data
  var charBuffer = new char[4096];
  var decoder = Encoding.UTF8.GetDecoder();

  int bytesRead;
  while ((bytesRead = stream.Read(buffer, 0, buffer.Length)) != 0)
  {
    var expectedChars = decoder.GetCharCount(buffer, 0, bytesRead);
    if (charBuffer.Length < expectedChars) charBuffer = new char[expectedChars];

    var charCount = decoder.GetChars(buffer, 0, bytesRead, charBuffer, 0);
    Console.Write(new string(charBuffer, 0, charCount));
  }

  client.Close();
}

Обратите внимание, что это не обрабатывает ошибки, поэтому не используйте его как есть в любом производственный код. Возможно, вы также захотите использовать методы Async, если вы ожидаете более нескольких одновременных подключений. Это просто для иллюстрации базового c способа обработки потока данных, получаемых по TCP.

Если вы хотите получить более глубокое представление о работе с TCP, у меня есть несколько очень простых примеров на https://github.com/Luaancz/Networking. Я не нашел хороших учебных пособий или примеров кода для C#, поэтому, если этого недостаточно, вам, вероятно, придется глубже изучить документацию по сокетам, TCP и всем прочим.

Или просто используйте существующую сетевую библиотеку, а не пытайтесь написать свою собственную :) TCP по-прежнему очень низкий уровень.

...