2015-03-12 6 views
3

У меня есть сервер, на котором работает MPD (демон музыкального плеера), который обменивается данными через сокеты. Теперь я пытаюсь реализовать протокол MPD в приложении хранилища Windows. В основном я посылаю команду и получаю список, который имеет последнюю строку «ОК». Пока список получателей меньше, чем буфер приема, все в порядке. Но если мне нужно загрузить данные, которые больше, чем буфер, начинается проводной материал.StreamSocket на WinRT не получает всех данных

При вызове SendCommand первый раз, когда я получаю только часть данных, остальное принимается при вызове SendCommand второй раз. При вызове еще раз я получаю все данные, как ожидалось. Когда это делается в программе WPF на том же компьютере, все в порядке.

Это мой код:

public async Task<string> SendCommand(MpdProtocol.MpdCommand command) 
    { 
     DataWriter writer = new DataWriter(streamSocket.OutputStream); 
     string res = string.Empty; 

     writer.WriteString(command.ToString()); 
     await writer.StoreAsync(); 
     res = await ReadResponse(); 

     writer.DetachBuffer(); 
     writer.DetachStream(); 
     return res; 
    } 

    private async Task<string> ReadResponse() 
    { 
     DataReader reader = new DataReader(streamSocket.InputStream); 
     reader.InputStreamOptions = InputStreamOptions.Partial; 
     StringBuilder response = new StringBuilder(); 

     const uint MAX_BUFFER = 8 * 1024; 
     uint returnBuffer = 0; 
     do 
     { 
      returnBuffer = await reader.LoadAsync(MAX_BUFFER); 
      response.Append(reader.ReadString(reader.UnconsumedBufferLength)); 

     } while (returnBuffer >= MAX_BUFFER); 

     reader.DetachBuffer(); 
     reader.DetachStream(); 

     return response.ToString(); 
    } 

Я играл с методом ReadResponse, но ничего не получалось.

Может ли кто-нибудь указать мне в правильном направлении?

+0

Я пробовал разные способы чтения данных из потока, и ничего не работало. Проблема в том, что «DataReader» перестает читать, но все же есть данные для приема. И почему это работает при вызове SendCommand в третий раз? – Steffen

+0

Я вижу две очевидные ошибки в вашем коде: вы не вызываете 'writer.FlushAsync()' после записи и перед отсоединением записи, и вы предполагаете, что один вызов 'LoadAsync()' всегда будет заполнять буфер, если только больше нет данных для чтения. Без [хорошего, _minimal_, _complete_ кода примера] (http://stackoverflow.com/help/mcve), который надежно воспроизводит проблему, было бы невозможно точно сказать, что вам нужно сделать, чтобы исправить код. Но я бы начал там. –

+0

(Я также подозрительно отношусь к временному использованию читателя и писателя ... Я бы подумал, что было бы лучше просто создать их один раз для каждого соединения и продолжать использовать их до тех пор, пока не будет выполнено соединение. Но я менее знаком с новой моделью ввода-вывода Windows Runtime, и, может быть, ваш код в противном случае полностью прекрасен в этом отношении. Не могу сказать точно). –

ответ

1

Наконец-то я нашел решение для работы связи: чтение байта потока байтом с помощью reader.ReadByte() и проверка каждой полученной строки (они разделены "\n") за то, что они «ОК».

Проблема reader.ReadString. Этот метод хорош, когда вы знаете, как долго вы будете пытаться получить строку. В моем случае я понятия не имею о размере строки. Все, что я знаю, это то, что в последней строке будет строка «ОК».

Моя ошибка состояла в том, чтобы верить - как упоминал Петр, - до тех пор, пока данные для извлечения регенерирующего буфера будут заполнены полностью, и только последний вызов reader.ReadString будет меньше максимального размера буфера. Я также пытался переписать функцию ReadResponse по-разному, но ничего не работало для reader.ReadString.