Как к дельте кодируют структуру C/C++ для передачи через сокеты

ruby script/generate migration add_fieldname_to_tablename fieldname:string

это - метод ярлыка, чтобы сделать точно, что Вы хотите. при необходимости в большем количестве управления, или если у Вас будет много столбцов для добавления, ответ H Andrew будет хорошо работать также.

5
задан guest 24 October 2009 в 19:14
поделиться

4 ответа

UDP не гарантирует, что данный пакет действительно был получен, поэтому кодирование того, что вы передаете, как «отличия от предыдущего времени» проблематично - вы не можете знать что ваш оппонент имеет то же представление о том, что «в последний раз» было . По сути, вам нужно было бы создать некоторые накладные расходы поверх UDP, чтобы проверить, какие пакеты были получены (помечая каждый пакет уникальным идентификатором) - все, кто пытался пройти этот маршрут, согласятся, что чаще всего вы обнаруживаете себя более или менее меньше дублирования потоковой инфраструктуры TCP поверх UDP ... только, скорее всего, не так надежно и хорошо проработано (хотя, по общему признанию, иногда вы можете воспользоваться очень особыми характеристиками ваших полезных нагрузок, чтобы получить некоторое скромное преимущество перед простым добрым старым TCP).

Должна ли ваша передача быть односторонней, отправитель к получателю? Если это так (т. Е. Для получателя неприемлемо отправлять подтверждения или повторные передачи), то вы действительно мало что можете сделать в этом направлении. Одна вещь, которая приходит на ум: если приемник может некоторое время не синхронизироваться, то отправитель может отправить два типа пакетов - один с полным изображением текущего значения структуры и идентифицирующий. уникальный тег, который должен отправляться не реже, чем каждые (скажем) 5 минут (так что реально получатель может быть рассинхронизирован до 15 минут, если он пропустит два из этих «больших пакетов»); один только с обновлением (diff) из последнего «большого пакета», включая уникальный тег, идентифицирующий большой пакет, и (например) версию XOR с кодировкой длины серии, о которой вы говорите.

Конечно, однажды подготовив прогон версия с кодировкой по длине, сервер будет сравнивать свой размер с размером всей структуры и отправлять пакет дельта-типа только в том случае, если экономия значительна, в противном случае он мог бы также отправить большой пакет немного раньше, чем необходимо (повышение надежности). Полученный будет отслеживать последний полученный уникальный тег большого пакета и применять только относящиеся к нему дельты (помогает избежать пропущенных пакетов и пакетов, доставленных не по порядку, в зависимости от того, насколько сложным вы хотите сделать своего клиента).

Необходимость управления версиями и т. Д., в зависимости от того, что именно вы имеете в виду (будут ли отправители и получатели с разными представлениями о том, как должен выглядеть C-макет структуры, должны регулярно общаться? как они рукопожатия о том, какие версии известны обоим? и т. д.), добавит еще целый ряд сложностей , но это на самом деле другой вопрос, и ваш основной вопрос, кратко изложенный в заголовке, уже достаточно велик; -).

Если вы можете позволить себе периодические мета-сообщения от получателя обратно отправителю (подтверждения или запросы на повторную отправку ), то в зависимости от различных числовых параметров в игре вы можете разработать различные стратегии. Я подозреваю, что подтверждения должны быть довольно частыми, чтобы принести много пользы, поэтому запрос на повторную отправку большого пакета (либо специально идентифицированного, либо «все, что у вас есть, самое свежее» ) может быть лучшей мета-стратегией для отсечения пространства опций (которое в противном случае грозит взрывом ;-). Если это так, то отправитель может блаженно игнорировать любую стратегию, которую использует получатель для запроса повторной отправки больших пакетов, и вы можете экспериментировать на стороне получателя с различными такими стратегиями без необходимости повторно развертывать отправителя.

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

4
ответ дан 14 December 2019 в 04:41
поделиться

Для дельта-кодирования:

1) Периодически отправлять «ключевые кадры» (например, раз в секунду). Ключевой кадр - это полная копия (а не дельта), так что, если вы потеряете связь по какой-либо причине, вы потеряете только небольшой объем данных, прежде чем сможете снова «получить сигнал». Используйте простой заголовок пакета, который позволяет вам определять начало пакета и знать, какой тип данных он содержит.

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

3) Добавить проверку CRC к пакету (поиск CRC32). Это позволит получателю проверить, что пакет был получен неповрежденным, позволяя им пропускать недопустимые пакеты.

ПРИМЕЧАНИЯ:

  • Будьте осторожны, делая это через UDP - это не дает гарантии, что ваши пакеты будут доставлены в том же формате. заказ вы их отправили. Очевидно, что дельта будет работать, только если пакеты в порядке. В этом случае вам нужно будет добавить некоторую форму идентификатора последовательности к каждому пакету (первый пакет - «1», второй пакет - «2» и т. Д.), Чтобы вы могли обнаруживать неупорядоченное получение. Возможно, вам даже понадобится сохранить буфер из «n» пакетов в приемнике, чтобы вы могли повторно собрать их в правильном порядке, когда вы придете для их декодирования (но, конечно, это может вызвать некоторую задержку). Вы, вероятно, также пропустите некоторые пакеты через UDP, и в этом случае вам придется подождать до следующего ключевого кадра, прежде чем вы сможете «повторно получить сигнал» - поэтому ключевые кадры должны быть достаточно частыми, чтобы избежать катастрофических сбоев. в вашем сообщении.

  • Рассмотрите возможность использования сжатия (например, zip и т. д.). Вы можете обнаружить, что полный пакет может быть создан удобным для zip способом (например, перегруппировать данные для группировки байтов, которые, вероятно, будут иметь одинаковые значения (особенно нули) вместе), а затем сжать так хорошо, что он будет меньше несжатой дельты, и вам вообще не нужно будет прилагать все усилия для дельт (и вам не придется беспокоиться об упорядочивании пакетов и т. д.).

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

3
ответ дан 14 December 2019 в 04:41
поделиться

Я не уверен, что дельта-кодирование значений в UDP, которое по своей природе ненадежно и не по порядку, будет особенно простым. Вместо этого я бы отправил идентификатор поля, которое изменилось, и его текущее значение. Это также не требует каких-либо изменений, если вы хотите добавить дополнительные поля в структуру данных, которую вы отправляете. Если вам нужен стандартный способ сделать это, посмотрите на SNMP; это может быть то, что вы можете добавить, или это может быть немного мешковатым для вас (он определяет имена полей глобально и использует ASN.1 - оба из которых обеспечивают максимальную совместимость, но за счет некоторых байтов в пакете).

1
ответ дан 14 December 2019 в 04:41
поделиться

Использовать RPC, например corba или буферы протокола

Использовать DTLS с опцией сжатия

Использовать упакованный формат

Изменяет существующую библиотеку сжатия заголовков

0
ответ дан 14 December 2019 в 04:41
поделиться