LINUX.ORG.RU

Задать правильный порядок данных

 , ,


0

2

Имеем источник данных, который посылает некоторую последовательность, порядок в которой важен, допустим ABCDEF причем момент получения данных не синхронизирован, а это значит, что при подключении к этому источнику мы можем получить и CDEFAB, и FABCDE, и т.д. Вопрос в том каким образом возможно выровнять данные, для получения необходимого порядка последовательности?

P.S. И да, значения не константны, но порядок постоянен т.е. например такой последовательности ACBDEF быть не может.


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

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

Если ты подключаешься к чему-то, наверное отбрасывать можешь себе позволить. Главное есть ли какое значение которое данные не могут содержать? Вот его и впиховать.

Просто и удобно. Или не то?

P.S. В ситуации работы например с UART который просто шлёт целые числа в едином потоке 186168496478981698746945879847 таким разделителем является банальный перевод строк, выделяющий из потока в котором непонятно где что отдельные значения температур. Вот и всё.

LINUX-ORG-RU ★★★★★
()
Последнее исправление: LINUX-ORG-RU (всего исправлений: 4)

получаешь весь пакет данных, после чего выстраиваешь по нужному порядку

или создаёшь пустой массив, после чего ловишь данные и расставляешь их по нужным индексам

других решений как-то не приходит на ум

anonymous
()
Ответ на: комментарий от pavel_l

Если нельзя вставить туда, то придётся вставит себе, в смысле вычислять динамически момент когда данные пошли ну точно корректные типа

while(true) /* входим в основной цикл чтения*/
{
    while(true) /* тут же перехватываем его и вычисляем точно точно правильное*/
    {  
        buff[i++] = get_byte(stream_data)
        if (i >= buff_size) 
        {
            if (data_is_correct(buff))
            {  /*как только узнали что всё пришло верное*/
               int x = 0
               /*передаём что набрали в основную обработку*/
               while(x++ != i)
               {
                  collect_input_data(buff[x])
               }
               /* валим сразу после этого от сюда*/
               break
            }else{
              /* не прошло проверку, в помойку и по новой */
              i = 0
              memset(buff,0,buff_size)
            }
        }
    }
    /*и уже продолжаем получать дальше всё как надо*/
    collect_input_data(get_byte(stream_data))
    ...
}
  • Либо ты должен мочь вычислить правильность данных на приёме
  • Либо ты должен мочь сказать где что на отдаче

Что удобнее то и сделать. Первое гибче, второе проще.

LINUX-ORG-RU ★★★★★
()
Последнее исправление: LINUX-ORG-RU (всего исправлений: 1)

Объявить какой-нибудь символ разделителем и в сообщении маскировать его комбинацией двух других. Стандартная в общем задача, посмотри как в hdlc сделано.

aiqu6Ait ★★★★
()
Ответ на: комментарий от pavel_l

В общем я так и не понял, есть у тебя уникальный символ (последовательность) начала пакета? Протокол вообще описан где-нибудь? Если нет, то может дамп десятка пакетов скинуть?

aiqu6Ait ★★★★
()

передача рингбуффера чтоли идет каждый раз?

или потоком типа latlngalt?

если второе, то втащить буффер, подвигать окно, собрать статистику.

если в данных есть какая-нибудь структура, то будет работать.

drsm ★★
()

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

Например, берем текстовый контейнер в формате JSON и будем передавать его по UDP/IP, причем каждый контейнер от символа { до символа } в своем UDP пакете. На приемной стороне UDP пакеты могут прийти в любой последовательности.

Обозначим:

  • «sn» - номер серии.
  • «n» - номер контейнера в серии. Если нужно, то отрицательное число может обозначать, что это финальный контейнер в серии, чтобы можно было передавать серии из разного количества контейнеров.
  • «e» - значение элемента.

Пусть начальный номер серии = 1, размещаем ABCDEF в контейнеры и отправляем:

{ "sn":"1", "n":"0", "e":"A" }
{ "sn":"1", "n":"1", "e":"B" }
{ "sn":"1", "n":"2", "e":"C" }
...
{ "sn":"1", "n":"-5", "e":"F" }

На приемной стороне не составит труда собрать из набора контейнеров всю серию, даже с контролем, что что-то не пришло:

{ "sn":"1", "n":"1", "e":"B" }
{ "sn":"1", "n":"2", "e":"C" }
{ "sn":"1", "n":"-5", "e":"F" }
...
{ "sn":"1", "n":"0", "e":"A" }

Формат контейнеров выбирается в зависимости от способа передачи, а JSON формат приведен просто для примера.

Vic
()
Последнее исправление: Vic (всего исправлений: 1)
Ответ на: комментарий от Vic

Для моего случая это явный оверхед.

Может я как-то запутанно объяснил и задача сводится к нахождению начала для кольцевого буфера? Только вот с учетом того, что данные передаются очень близкие по значению и выделение какой либо структуры в них затруднительно, то без наличия какого-то разделения (символьного/временного/…) эта задача вряд ли решаема?

pavel_l
() автор топика
Ответ на: комментарий от pavel_l

Все дело в асинхронности процесса генерации данных и их получения, т.е. вот в этом:

момент получения данных не синхронизирован

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

Ничего другого наука не придумала.

Vic
()
Ответ на: комментарий от pavel_l

Может я как-то запутанно объяснил и задача сводится к нахождению начала для кольцевого буфера?

«Кольцевой буфер» - это оптимальный способ реализации хранилища типа «очередь», т.к. при добавлении или извлечении элементов не нужно копировать все остальные элементы внутри очереди.

А в «очереди» все элементы упорядочены и не перемешиваются.

Доступ к «очередь» можно передавать между программами или потоками, но тогда каждый получает очередь в свое распоряжение на время и только целиком, т.к. это по сути одна переменная пусть и сложной структуры.

Vic
()
Последнее исправление: Vic (всего исправлений: 1)

в сипе в каждом пакете, например, поле CSeq имеется.

rfc3261:

8.1.1.5 CSeq

   The CSeq header field serves as a way to identify and order
   transactions.  It consists of a sequence number and a method.  The
   method MUST match that of the request.

Простыми словами, для каждого метода в протоколе sip имеется счетчик, который монотонно возрастает в рамках сессии.

aol ★★★★★
()
Последнее исправление: aol (всего исправлений: 2)
Ответ на: комментарий от pavel_l

Если нет разделителя - тогда должен быть механизм валидации последовательности байт (пакета) - например crc. Если нет ни того, ни другого - то никак.

anonymous
()

Смысл в том, чтобы при получении очередного куска данных поместить его на нужное место в итоговой последовательности, то есть держать эту последовательность всегда отсортированной? Звучит как https://en.wikipedia.org/wiki/Heap_(data_structure).

В плюсцах же есть реализации кучи? Ведь есть же?

Nervous ★★★★★
()
Ответ на: комментарий от Nervous

Нет, смысл не в этом Есть источник из которого валятся байты (может быть даже биты)

byte0 byte1 byte2 byte3 byte4 byte5 byte0 byte1 byte2 …

Этот источник живет своей жизнью независимо от того слушает его кто-то или нет. У каждого байта свое назначение в зависимости от его номера в закольцованной последовательности. Т.е. в byte0 лежит значение параметра A, в byte1 значение параметра B и т.д. ТС начинает слушать эту карусель в случайный момент времени, т.е. например с byte2, а не с byte0. Как ему теперь понять какой байт к какому параметру относится - ответ никак. Или разделитель должен быть например равный 0x42

byte0 byte1 byte2 byte3 byte4 byte5 0x42 byte0 byte1 byte2 …

Но тогда параметры A B C … не могут принимать значение 0x42

Или crc8 например

byte0 byte1 byte2 byte3 byte4 byte5 crc8 byte0 byte1 byte2 …

anonymous
()
Ответ на: комментарий от anonymous

Есть источник из которого валятся байты

в byte0 лежит значение параметра A, в byte1 значение параметра B и т.д.

ТС начинает слушать эту карусель в случайный момент времени

И они ещё до кучи могут приходить в произвольном порядке, ага. Не, ну тут без либастрала никак не обойтись, ящетаю.

Потому что вот прочитал ты байт — а информацию о том, что это за байт, тебе взять тупа неоткуда. Ни в самом байте, ни в его месте в последовательности этой информации нет.

Nervous ★★★★★
()
Последнее исправление: Nervous (всего исправлений: 2)
Ответ на: комментарий от anonymous

Собственно всё так и есть, ну и после обсуждения здесь пришел к тому же выводу - «никак». На данный момент пробую аппаратное решение со стороны передатчика.

pavel_l
() автор топика