LINUX.ORG.RU

Контроль отправки данных по сети

 ,


1

3

Имеется некая структура, которую я передаю по сети.
Сейчас, когда структура сериализуется, я делаю так (псевдокод):

static uint32_t magicNumberBegin = ...
static uint32_t magicNumberEnd = ...
stream << magicNumberBegin << struct << magicNumberEnd;
send(stream);
на другой стороне проверяю сходятся ли начальный и конечные числа, если да - считаю что передача удалась, то есть:
read(stream);
stream >> magicNumberBeginTmp >> struct >> magicNumberEndTmp;
if (magicNumberBeginTmp == magicNumberBegin && magicNumberEndTmp == magicNumberEnd) {
    // OK
} else { 
    //fail
}


Размер структуры - ~60 килобайт.

Вопрос: правильно ли я делаю? Если нет, какие предложение будут?
Считать, что порядок байт не имеет значения.

Вопрос 2: как контролировать, что с serial порта считались валидная строка? Строка будет <20 символов. Планирую приблизительно так же.

//device
send(magicNumberBegin, stringSize, string);
//reader
read(magicNumberBeginTMP, stringSizeTMP, string);
if (magicNumberBeginTmp == magicNumberBegin && stringSizeTMP == string.size()) {
    //OK
} else {
    //fail
}

★★★★

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

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

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

magicNumberBegin и magicNumberEnd uint32_t в программе.
Структура - большая строка (~60 килобайт).

Отправка/получение средствами Qt.

ymuv ★★★★
() автор топика

Если TCP то норм. Главное проверить, что реально ушло 60к и принято 60к. Ну и про выравнивание/упаковку уже сказали

anonymous
()

magic нужен чтобы сразу завершить чтение не пытаясь как-то дальше интерпретировать структуру, ~ простая защита от неправильного клиента. Для проверки целостности пакета нужно использовать какую-нибудь контрольную сумму, закрывающий magicNumber бесполезен. Вместо простого magic есть смысл сделать хедер из {magic, version, size} и только потом уже гнать структуру размером size.

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

Посмотри как устроены IP пакеты (IP header format) . Если порядок байт значения не имеет, то можно применить pragma pack https://habrahabr.ru/post/142662/ и маппить через указатель просто. Вообще тебе не нужен magicNumberEnd, лучше вместо него добавить контрольную сумму в заголовок, если боишься проблем с потерей данных и т.п.

Norgat ★★★★★
()

Можешь ещё Crc32 добавить

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

magicNumberBegin и magicNumberEnd uint32_t в программе.
Структура - большая строка (~60 килобайт).

Это всё круто, но что будет, если у тебя в данных встретится твоё magicNumberEnd? Большие мальчики и девочки передают размер перед собственно данными.

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

Там работает QDataStream. Я не вручную распаковываю.

Большие мальчики и девочки передают размер перед собственно данными.

Так нормально будет?

stream << magicNumberBegin << sizeof(struct) << struct;

//client

read(stream);
stream >> magicNumberBeginTmp >> sizeTMP>>  struct;
if (magicNumberBeginTmp == magicNumberBegin && sizeTMP == sizeof(struct) {
    // OK
} else { 
    //fail
}


И еще вопрос: как контролировать, что с serial порта считались валидная строка? Строка будет <20 символов. Планирую приблизительно так же.

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

Неправильно. Зачем надеяться на какие-то маркеры, когда достаточно использовать формат, не допускающий некорректного парсинга?

static uint32_t version = 2;
stream << version << struct;
uint32_t version;
stream >> version;
if (version == 2) {
    stream >> struct;
} else if (version == 1) {
    stream >> legacy_v1_struct;
    struct = struct::from_legacy_v1(legacy_v1_struct);
} else {
    throw std::runtime_error("Bad protocol version");
}

Или использовать протоколы которые сами заботятся о совместимости, типа protobuf.

slovazap ★★★★★
()

Вопрос: правильно ли я делаю?

Нет.

Если нет, какие предложение будут?

Использовать CRC.

Deleted
()

Лол, а если у тебя половину структуры обрежет, а в данных следующей структуры встретится твой маркер?

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

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

Ещё один. TCP-то тут причем, болезный? Он потоковый.

kirk_johnson ★☆
()

передающий никак не сможет убедится, что отправленное дошло до получателя, если только сам получатель не скажет ему об этом, например проверив контрольную сумму принятых данных

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

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

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

да, но вероятность коллизии контрольной достаточно суммы мала, и так сойдет

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

неа, не так, если получатель не отправит обратно пришедшую посылку, только так можно 100% гарантировать доставку инфы.

Обратная посылка тоже может испортиться сформировав правильные данные, 100%-го метода защиты не существует.

mashina ★★★★★
()

Передавай magic и size. Но от валидации данных это не избавляет.

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

Вопрос: правильно ли я делаю?

нет

какие предложение будут?

tcp + объявление длины если заранее не известна.

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

маловероятно, если данные включали crc

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

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

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

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

Добавил контрольную сумму и размер. Вероятность коллизии небольшая.

ymuv ★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.