C # NetworkStream ReadAsync, данные разделены между буферами - PullRequest
0 голосов
/ 29 сентября 2018

В настоящее время я использую метод ReadAsync в NetworkStream, и до сих пор он был довольно стабильным.Проблема возникает, когда данные, полученные с сервера, больше, чем сам буфер.

ReadCallBack предполагает, что буфер содержит полное и правильное сообщение, так как новый буфер создается при каждом вызове BeginAsyncRead.Таким образом, когда ответ слишком велик для одного буфера, он разделяется на несколько операций чтения и, следовательно, на несколько буферов.

Мой ReadCallBack тогда предполагает, что каждый буфер является независимым сообщением (вместо того, чтобы добавлять их вместе), и завершается неудачей десериализации на обоих.

Мой вопрос: , , как правильно обрабатывать сообщения, размер которых превышает размер буфера, особенно если вы хотите выполнять чтение асинхронно? Сам персонаж может быть разделен между двумя буферами, так что это довольно сложно.

Ниже приведен мой код для ReadAsync и ReadCallBack.

    public async Task ReadForever() {
        while(this.IsConnected) {
            await BeginAsyncRead();
        }
    }


    public async Task BeginAsyncRead() {
        if (this.Stream.CanRead) {
            try {
                ReceiverState readState = new ReceiverState(this.Stream);
                var task = this.Stream.ReadAsync(readState.buffer, 0, ReceiverState.bufferSize);
                await task.ContinueWith(bytesRead => ReadCallBack(bytesRead.Result, readState));
            }
            catch (Exception e) {
                Console.WriteLine("Error");
            }
        } else {
            Console.WriteLine("Unreadable stream");
        } 
    }

private void ReadCallBack(int numBytesRead, ReceiverState state) {
    if (numBytesRead > 0) {
        string payload = Encoding.ASCII.GetString(state.buffer, 0, numBytesRead);
        string[] responses = payload.Split(new string[] {"\n"}, StringSplitOptions.RemoveEmptyEntries);
        foreach (string res in responses){                    
            var t = Task.Run(() => this.OnRead(res));
        }
    } else {
        Console.WriteLine("Corrupted number of bytes received");
    }
}

Примечание. Все ответы, отправленные сервером, содержат в конце символ новой строки.Примечание: ReadForever вызывается внутри Task.Run, мое приложение может получать сообщения с сервера в виде уведомлений, поэтому я всегда должен читать входящие сообщения (я не знаю, когда уведомление может прийти).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...