uint16_t в массиве char
Для школьного проекта мне нужно разработать TFTP-сервер на C. Я должен собрать пакет в массиве char следующим образом:
2 bytes 2 bytes n bytes
+--------+-----------+--------+
| CODE | Block # | Data |
+--------+-----------+--------+
Вот как я собираю этот пакет:
int tftp_make_data(char *buffer, size_t *length, uint16_t block, const char *data, size_t n) {
memset(buffer, 0, *length);
*length = 0;
*(buffer) = DATA;
*length += sizeof(uint16_t);
*(buffer + *length) = block;
*length += sizeof(uint16_t);
memcpy(buffer + *length, data, n);
*length += n;
return 0;
}
Эта функция заполнения buffer
с содержимым пакета и заполнить length
с размером пакета. Это работает нормально, если block
ниже 128. Если он больше 128, он становится -128.
Вы можете мне помочь?
1 ответ
Если что-то не имеет размер в один байт, вы не можете назначить его *buffer
, Оба эти назначения неверны:
*(buffer) = DATA;
*(buffer + *length) = block;
Когда ты пишешь uint16_t
использовать memcpy
:
uint16_t dataToWrite = ...;
memcpy(buffer + *length, &dataToWrite, sizeof(uint16_t));
Вы еще не закончили, потому что вам нужно решить, что назначить dataToWrite
, Если вы делаете это
uint16_t dataToWrite = block;
данные, передаваемые по проводам, будут в аппаратном порядке, что никогда не должно происходить. Вместо этого вам нужно использовать один из hton
Семейные функции для преобразования вашего номера в сетевой формат:
uint16_t dataToWrite = htons(block);
Я проверяю это на той же машине, только с
printf("block : %d\n", packet[sizeof(uint_16)]);
Это неверно по той же причине, что и назначение: packet[sizeof(uint_16)]
делает int
или же unsigned int
от char
/uint8_t
значение хранится в позиции sizeof(uint_16)
и он также игнорирует другой байт.
Чтобы исправить это вам нужно использовать memcpy
снова. Конечно, если вы использовали htons
на стороне записи, вы должны использовать ntohs
перед печатью:
uint16_t dataToPrint;
memcpy(dataToPrint, &packet[sizeof(uint16_t)], sizeof(uint16_t));
dataToPrint = ntohs(dataToPrint);
printf("block : %u\n", dataToPrint);