2015-09-29 4 views
0

Я провел последние несколько дней, пытаясь прочитать из объекта NetworkStream, используя как BeginRead, так и методы Read, однако оба метода затрудняют и ненадежны.Ожидание определенной информации в объекте NetworkStream

Во-первых, «Чтение» потребовало от меня спать поток и ожидало, что правильные данные будут присутствовать при завершении сна. Как так:

cmd = System.Text.Encoding.ASCII.GetBytes(CommandString + "\r"); 
ns.Write(cmd, 0, cmd.Length); 
Thread.Sleep(5000); 
int _bytes = ns.Read(output, 0, output.Length); 
responseOutput = System.Text.Encoding.ASCII.GetString(output, 0, _bytes); 
Console.Write(responseOutput); 

Это работало 80% времени, так как задержка на сервер колебались в течение дня, я также попробовал метод, ниже которого я чувствую себя плохо сконструированный, то, что будет наиболее эффективным способ опроса данных, который соответствует множеству условий, которые не сжигают процессор и не теряют время?

bool connection_check = false; 
String[] new_connection_array = new String[] { "processed successfully", "invalid", "Command not recognised. Check validity and spelling" }; 

do 
{ 
    int view_bytes = ns.Read(output, 0, output.Length); 
    responseOutput += System.Text.Encoding.ASCII.GetString(output, 0, view_bytes); 

    foreach (String s in new_connection_array) 
     if (responseOutput.IndexOf(s) > -1) 
      connection_check = true; 

} while (connection_check == false); 

Заранее спасибо

Edit:

public bool SendCommandAndWait(Byte[] command, Regex condition) 
     { 
      if (callback == null) 
      { 
       SendCommand(command); 

       callback = ar => 
       { 
        int bytesEnd = ns.EndRead(ar); 
        int bytes = bytesEnd; 

        // Process response 
        responseOutput += System.Text.Encoding.ASCII.GetString(output, 0, bytes); 

        // Check if we can return 
        if (condition.IsMatch(responseOutput)) 
         return; // Yes, there is a match... return from the async call 
        else // No match, so loop again 
         ns.BeginRead(output, 0, output.Length, callback, null); // Call the loop again 
       }; 
       ns.BeginRead(output, 0, output.Length, callback, null); 
      } 

      // Because the callback is fired into a different thread and the program continues, we need to loop here so the program doesn't continue without us 
      do 
      { 
       Thread.Sleep(1000); 
       //Console.WriteLine(responseOutput); 
      } while (!condition.IsMatch(responseOutput)); 

      if (condition.IsMatch(responseOutput)) 
      { 
       callback = null; 
       return true; 
      } 
      else 
       return false; 

     } 
+0

Этот вопрос задается ежедневно. Сокеты TCP предлагают поток данных, а не сообщения. Вам не нужен Thread.Sleep(), вам нужен протокол приложения для определения границ сообщений, чтобы вы знали, когда получили целое сообщение. Не используйте сокеты, если у вас нет очень веской причины, используйте концепцию более высокого уровня, такую ​​как SOAP через WCF. – CodeCaster

+0

Я знаю, что они не работают, как сообщения, поэтому я вроде как «собираю» поток до тех пор, пока данные не совпадут с условием. Однако эта программа будет работать без головы, как служба на сервере и будет обращаться к Telnet-клиент, с которым я не контролирую. Afaik, работающий с Sockets - единственный способ пойти, не говоря уже о огромном изменении дизайна не на карточках – Syphonx

+0

@CodeCaster, затем создайте или найдите вопрос, который можно использовать в качестве цели, чтобы закрыть их как дубликаты. Я думаю, что для каждой платформы необходим вопрос, чтобы обеспечить хороший пример кода. –

ответ

0

BeginRead позволят вам определить действие, которое выполняется, когда BeginRead закончена. Обратите внимание, что это не то же самое, что когда вы читали все, что хотите читать. Вот почему read возвращает количество прочитанных байтов. Если вы ожидаете прочитать 20 байт и получите 10, вам нужно будет прочитать еще 10 байтов.

От https://msdn.microsoft.com/en-us/library/system.net.sockets.networkstream.beginread(v=vs.110).aspx:

Метод BeginRead читает столько данных, сколько есть в наличии, вплоть до числа байтов, заданное параметром размера.

Если вы хотите, чтобы исходный поток блокировался после вызова метода BeginRead, используйте метод WaitOne.

+0

Привет, Vegahyo, я уже пытался использовать метод BeginRead (см. Править), но обратный вызов не всегда возвращает указанное условие, любые идеи? Спасибо – Syphonx

+0

Вам нужно подождать. Но помните, что чтение не всегда читает байты, которые вы хотите прочитать, вам нужно проверить, соответствует ли количество прочитанных байтов тому, что вы ожидаете. Pseudo code: public static ManualResetEvent allDone = new ManualResetEvent (false); BeginRead (blah, blah, blah, callback) allDone.WaitOne(); void callback() { всеDone.Set(); } – Vegahyo

 Смежные вопросы

  • Нет связанных вопросов^_^