Использование первого бита в качестве флага в беззнаковом int - PullRequest
1 голос
/ 20 июня 2019

Я пытаюсь использовать первый бит целого без знака в качестве флага, если клиент как сервер должен повторно ввести ключ для своих ключей шифрования.Я хотел бы использовать оставшуюся часть unsigned int в качестве длины для оставшихся отправляемых данных.

В настоящее время я пытаюсь это сделать, но, похоже, это не работает.

unsigned int payloadLength;
read(sock, &payloadLength, sizeof(payloadLength));
short bit = (payloadLength >> 0) & 1U; // get first bit

payloadLength &= 1UL << 0; // set first bit to 0
payloadLength = ntohl(payloadLength);

if (bit == 1) 
   //rekey
else
  //read more data

Флаг повторного ввода, кажется, установлен правильно, но при попытке получить длину он всегда заканчивается как неправильное число.

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

Ответы [ 2 ]

3 голосов
/ 20 июня 2019

Давайте посмотрим на этот код:

short bit = (payloadLength >> 0) & 1U; // get first bit
payloadLength &= 1UL << 0; // set first bit to 0
payloadLength = ntohl(payloadLength);

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

/* CAUTION: This still has errors! */
payloadLength = ntohl(payloadLength);
short bit = (payloadLength >> 0) & 1U; // get first bit
payloadLength &= 1UL << 0; // set first bit to 0

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

/* CAUTION: This still has errors! */
payloadLength = ntohl(payloadLength);
short bit = payloadLength & 1U; // get first bit
payloadLength &= 1UL; // set first bit to 0

Ваш код для извлечения последнего бита числа правильный.Он замаскирует все, кроме младшего бита, а затем сохранит значение в переменной bit.(Из любопытства, есть ли причина, по которой вы сохраняете это как short? Если вы ищете логическое «нужно ли мне перекодировать это?», Вы можете просто пойти с bool и написатьчто-то вроде

bool reencode = (payloadLength & 1U) != 0;

Однако решать вам.)

Однако ваш код для clear последний бит неверен.Прямо сейчас, когда вы пишете

payloadLength &= 1UL; // set first bit to 0

, вы фактически делаете противоположное тому, что планировали - вы очищаете каждый бит , кроме первого.Это потому, что если вы И payloadLength со значением, вы обнуляете каждый бит в payloadLength, за исключением битов, равных 1 в 1UL.Однако 1UL имеет только 1 бит в последней позиции.Возможно, вы хотели написать что-то вроде

payloadLength &= ~1UL; // set first bit to 0

, где оператор ~ переворачивает биты вашей маски.В целом, это даст вам следующее:

payloadLength = ntohl(payloadLength);
short bit = payloadLength & 1U; // get first bit
payloadLength &= ~1UL; // set first bit to 0

У меня есть еще один последний вопрос.Таким образом, переназначая младший бит числа, вы требуете, чтобы длина вашей полезной нагрузки всегда была четным числом, поскольку вы используете бит 1 длины полезной нагрузки, чтобы кодировать, нужно ли повторно вводить ключ.Если ты в порядке с этим, отлично!Вам не нужно ничего делать.

С другой стороны, если это проблема, у вас есть несколько вариантов, которые я оставлю вам на выбор:

  1. Вместо использования младшего значащего бита, используйте самый -значащий бит.Это вызовет проблемы, если вы попытаетесь отправить полезные данные размером 2 31 или выше, хотя.

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

  3. Не используйте биты вообще для кодирования этого!Вместо этого отправьте длину полезной нагрузки, затем начните ее с заголовка, в котором указывается, нужно ли повторно вводить данные и т. Д. При этом используется больше байтов на полезную нагрузку, но при этом вы получаете больше гибкости в будущем (что, если вам нужно отправить другие флагихорошо?)

Надеюсь, это поможет!

1 голос
/ 20 июня 2019

payloadLength &= 1UL << 0; обнулит все биты, кроме первого.payloadLength &= ~1UL; обнулит первый бит.

...