Что хороший метод состоит в том, чтобы обработать основанные на строке потоки сети I/O?

Ваше событие смахивания выполнялось вне контекста Angular, вы должны либо использовать привязку события в своем HTML-шаблоне, либо использовать Renderer2 , чтобы добавить обработчик добавления события в ElementRef , чтобы Angular к выполнить обнаружение изменений.

Вот обновленная игровая площадка.

6
задан Erik Funkenbusch 8 February 2009 в 00:35
поделиться

2 ответа

Это - вполне интересный вопрос. Решение для меня в прошлом состояло в том, чтобы использовать отдельный поток с синхронными операциями, как Вы предполагаете. (Мне удалось обойти большинство проблем с блокированием сокетов с помощью блокировок и большого количества обработчиков исключений.) Однако, использование встроенных асинхронных операций обычно желательно, поскольку оно допускает истинный уровень ОС асинхронный ввод-вывод, таким образом, я понимаю Вашу точку.

Хорошо я пошел и записал класс для выполнения, что я полагаю, что Вам нужно (относительно чистым способом, который я сказал бы).Сообщите мне, что Вы об этом думаете.

using System;
using System.Collections.Generic;
using System.IO;
using System.Text;

public class AsyncStreamProcessor : IDisposable
{
    protected StringBuilder _buffer;  // Buffer for unprocessed data.

    private bool _isDisposed = false; // True if object has been disposed

    public AsyncStreamProcessor()
    {
        _buffer = null;
    }

    public IEnumerable<string> Process(byte[] newData)
    {
        // Note: replace the following encoding method with whatever you are reading.
        // The trick here is to add an extra line break to the new data so that the algorithm recognises
        // a single line break at the end of the new data.
        using(var newDataReader = new StringReader(Encoding.ASCII.GetString(newData) + Environment.NewLine))
        {
            // Read all lines from new data, returning all but the last.
            // The last line is guaranteed to be incomplete (or possibly complete except for the line break,
            // which will be processed with the next packet of data).
            string line, prevLine = null;
            while ((line = newDataReader.ReadLine()) != null)
            {
                if (prevLine != null)
                {
                    yield return (_buffer == null ? string.Empty : _buffer.ToString()) + prevLine;
                    _buffer = null;
                }
                prevLine = line;
            }

            // Store last incomplete line in buffer.
            if (_buffer == null)
                // Note: the (* 2) gives you the prediction of the length of the incomplete line, 
                // so that the buffer does not have to be expanded in most/all situations. 
                // Change it to whatever seems appropiate.
                _buffer = new StringBuilder(prevLine, prevLine.Length * 2);
            else
                _buffer.Append(prevLine);
        }
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    private void Dispose(bool disposing)
    {
        if (!_isDisposed)
        {
            if (disposing)
            {
                // Dispose managed resources.
                _buffer = null;
                GC.Collect();
            }

            // Dispose native resources.

            // Remember that object has been disposed.
            _isDisposed = true;
        }
    }
}

Экземпляр этого класса должен быть создан для каждого NetworkStream, и функция Процесса должна быть вызвана каждый раз, когда новые данные получены (в методе обратного вызова для BeginRead перед вызовом следующего BeginRead, который я вообразил бы).

Примечание: Я только проверил этот код с данными тестирования, не фактические данные, переданные по сети. Однако я не ожидал бы различий...

Кроме того, предупреждение, что класс, конечно, не ориентирован на многопотоковое исполнение, но пока BeginRead, не выполняется снова, пока текущие данные не были обработаны (поскольку я предполагаю, что Вы делаете), не должно быть никаких проблем.

Надеюсь, что это работает на Вас. Сообщите мне, остаются ли там проблемами, и я попытаюсь изменить решение иметь дело с ними. (Могла быть некоторая тонкость вопроса, который я пропустил, несмотря на чтение ее тщательно!)

5
ответ дан 17 December 2019 в 04:53
поделиться

То, в чем Вы объясняете, Вы - вопрос, напоминает мне многая строки ASCIZ. (текст ссылки). Это может быть полезным запуском.

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

Как я приблизился, мое решение было, я отправлю что-то как 5HELLO, поэтому сначала я видел бы 5 и знал бы, что у меня было длина сообщения 5, и для этого сообщение, в котором я нуждался, было 5 символами. Однако, если бы на моем асинхронном чтении, я только добрался 5HE, то я видел бы, что у меня есть длина сообщения 5, но я только смог считать 3 байта от провода (Давайте примем символы ASCII). Из-за этого я знал, что пропускал некоторые байты, и сохраненный, что я имел в буфере фрагмента. У меня был один буфер фрагмента на сокет, для этого избегая любых проблем синхронизации. Грубый процесс.

  1. Читайте из сокета в массив байтов, запишите, сколько байтов был считан
  2. Сканирование через байт байтом, пока Вы не находите символ новой строки (это становится очень сложным, если Вы не получаете символы ASCII, но символы, которые могли бы быть несколькими байтами, Вы идете, Вы являетесь собственными для этого),
  3. Поворот Вы - буфер frag в строку и добавляете, Вы читаетесь буфер вплоть до новой строки к нему. Отбросьте эту строку как завершенное сообщение на очередь или своего собственного делегата, чтобы быть обработанными. (можно оптимизировать эти буферы путем фактического наличия, Вы читаетесь сокет, пишущий в тот же массив байтов, как Вы - фрагмент, но это более трудно объяснить),
  4. Продолжите цикличное выполнение через, каждый раз, когда мы находим новую строку, создаем строку из расположения байта от зарегистрированного запуска / конечное положение и отбрасывание на очереди / делегат к обработке.
  5. После того как мы поражаем конец нашего буфера чтения, копируем что-либо, что это оставляют в буфер frag.
  6. Назовите BeginRead на сокете, который перейдет к шагу 1. когда данные доступны в сокете.

Затем Вы используете другой Поток для чтения, Вы - очередь сообщений incommign или просто позволяете Пулу потоков обработать его с помощью делегатов. И сделайте любую обработку данных, которую необходимо сделать. Кто-то исправит меня, если я буду неправ, но существуют очень небольшие проблемы синхронизации потока с этим, так как можно только читать или ожидать для чтения из сокета в любой момент, таким образом, никакое беспокойство о блокировках (кроме того, если Вы заполняете очередь, я использовал делегатов в своей реализации). Существует несколько деталей, на которых необходимо будет удаться, Вы являетесь собственными, как то, как большой из frag буферизуют для отъезда, если Вы получаете 0 новых строк, когда Вы делаете чтение, все сообщение должно быть добавлено к буферу фрагмента, ничего не перезаписывая. Я думаю, что это выполнило меня приблизительно 700 - 800 строк кода в конце, но это включало материал установления соединения, согласование для шифрования и несколько других вещей.

Эта установка, выполненная очень хорошо для меня; я смог выполнить до 80 Мбит/с на LAN Ethernet на 100 Мбит/с с помощью этой реализации Opteron на 1.8 ГГц включая обработку шифрования. И так как Вы связываетесь с сокетом, сервер масштабируется, так как несколько сокетов могут работаться на одновременно. При необходимости в объектах, обработанных в порядке необходимо будет использовать очередь, но если порядок не будет иметь значения, то делегаты дадут Вам очень масштабируемую производительность из пула потоков.

Надежда, которой это помогает, не предназначенный, чтобы быть полным решением, но направлением, в котором можно начать смотреть.

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

0
ответ дан 17 December 2019 в 04:53
поделиться
Другие вопросы по тегам:

Похожие вопросы: