2016-12-07 3 views
0

Пакеты данных отправляются от TcpListener до TcpClient через NetworkStream. Пакеты не большие (5 байт), но идут с большой частотой (около 1000 в секунду и более). Можете ли вы дать мне совет, как я могу обработать его наиболее эффективно? Теперь я использую async для получения потока, который заполняет буфер, а затем я разбиваю его на пакеты. После этого процесс повторяется. Но в какой-то момент я теряю истинную последовательность.C# Как лучше использовать NetworkStream?

s является NetworkStream.

Пакет имеет 2 поля: Тип (1 байт (байт)) и значение (4 байта (INT))

MAXVALUEPACKET = 4096

Клиент Код:

async Task process() 
    { 
     bool flag = false; 
     while (true) 
     { 
      byte[] actionBuffer; 
      flag = false; 
      actionBuffer = await ReadFromStreamAsync(); 
      while (!flag) 
      { 
       byte type = actionBuffer[0]; 
       int value = 0; 
       if (type > 0) 
       { 
        byte[] valueBytes = { actionBuffer[4], actionBuffer[3], actionBuffer[2], actionBuffer[1] }; 
        value = BitConverter.ToInt32(valueBytes, 0); 
        actionBuffer = actionBuffer.Skip(5).ToArray(); 
        CommonVariables.RawMessages.Add(new KeyValuePair<byte, int>(type, value)); 
        OnHandler(); 
       } 
       else 
        flag = true;      
      }  
     } 
    }   
    byte[] buf = new byte[MAXVALUEPACKET]; 
    async Task<byte[]> ReadFromStreamAsync() 
    { 
     await s.ReadAsync(buf, 0, MAXVALUEPACKET); 
     return buf; 
    } 
+0

['ReadAsync'] (https://msdn.microsoft.com/en-us/library/hh137813 (v = vs.110) .aspx):« Значение параметра * TResult * содержит общее число байтов, считанных в буфер. Значение результата может быть меньше количества запрошенных байтов, если количество доступных в настоящее время байтов меньше запрошенного числа « –

+0

И, самое главное, абстракция TCP представляет собой поток байтов. Нет никакой гарантии, что каждый вызов «Отправить» на одном конце будет соответствовать 1-1 с вызовом «Получить» на другом. Если вы хотите «Пакеты» или «Сообщения», вы должны * * реализовать плавную логику поверх TCP или перейти к абстракции более высокого уровня. –

+0

@Damien_The_Unbeliever Да, спасибо! Читайте только 5 байтов, стало намного лучше! – Krelembra

ответ

0

Установка MAXVALUEPACKET = 5 в читать точно каждые 5 байт может помочь избежать потери байтов:

 const int MAXVALUEPACKET = 5; 
     async Task process() 
     { 
      while (true) 
      { 
       var actionBuffer = await ReadFromStreamAsync(); 
       byte type = actionBuffer[0]; 
       int value = 0; 
       if (type > 0) 
       { 
        byte[] valueBytes = { actionBuffer[4], actionBuffer[3], actionBuffer[2], actionBuffer[1] }; 
        value = BitConverter.ToInt32(valueBytes, 0); 
        CommonVariables.RawMessages.Add(new KeyValuePair<byte, int>(type, value)); 
        OnHandler(); 
       } 
      } 
     } 

     async Task<byte[]> ReadFromStreamAsync() 
     { 
      await s.ReadAsync(buf, 0, MAXVALUEPACKET); 
      return buf; 
     } 

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