URL: https://www.opennet.me/cgi-bin/openforum/vsluhboard.cgi
Форум: vsluhforumID9
Нить номер: 7362
[ Назад ]

Исходное сообщение
"куда пихать byte,word,dword ?"

Отправлено Ivanoff , 12-Май-08 14:14 
Я начинающий :) пишу сетевую программку для некоторого протокола.
Проблема встала куда запихать пакет, пакет примерно выглядит так:
тип
byte type
word head
dword body
И того пакет 6 байт.

пока делаю так, пакет получаю в буффер char buff[];
а потом, когда надо анализировать, например посмотреть внутренности делаю так:
cout << "Type: " << buff[0] << endl;
cout << "Head: " << (int)buff[1]*10+buff[2] << endl;
cout << "Body: " << buff[3]*100+buff[4]*100+buff[5]*10+buff[6] << endl;

1. На сколько это корректно?
2. Может есть способы поэлегантнее доставать данные из пакета например body?
3. Есть ли какие нибудь стандартные типы(C/C++) для хранения байта, слова, двойного слова?



Содержание

Сообщения в этом обсуждении
"куда пихать byte,word,dword ?"
Отправлено NuINu , 12-Май-08 15:13 
>Я начинающий :) пишу сетевую программку для некоторого протокола.
>Проблема встала куда запихать пакет, пакет примерно выглядит так:
>тип
>byte type
>word head
>dword body
>И того пакет 6 байт.

это из какого языка типы? интересно как красивая цифра 6 получилась.

>
>пока делаю так, пакет получаю в буффер char buff[];
>а потом, когда надо анализировать, например посмотреть внутренности делаю так:
>cout << "Type: " << buff[0] << endl;
>cout << "Head: " << (int)buff[1]*10+buff[2] << endl;
>cout << "Body: " << buff[3]*100+buff[4]*100+buff[5]*10+buff[6] << endl;

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

>
>1. На сколько это корректно?
>2. Может есть способы поэлегантнее доставать данные из пакета например body?
>3. Есть ли какие нибудь стандартные типы(C/C++) для хранения байта, слова, двойного
>слова?

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


"куда пихать byte,word,dword ?"
Отправлено Ivanoff , 12-Май-08 16:43 
>это из какого языка типы?
>

Это... не из какого это выдержка из описания протокола. Как бы вроде известно что:
byte - байт это 8 бит. Бит это минимальная единица информации :) может принимать значения 0 или 1 :)

> интересно как красивая цифра 6 получилась.

Да, вы правы ) опечатка вышла поле Type(1 байт),Head (word = 2 байта),
Body (dword = 4 байта ) в итоге имеем пакет 1+2+4=7 байт.

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

это десятки. хм, насчет порядка в word, в левом байте - старший, в правом младший.

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

С языком проблем нет, с конструкцией struct знаком.

Про то где хранить байт,слово, двойное слово и как выделять их из массива байт вы не сказали не слова ( имхо вопрос не раскрыт.



"куда пихать byte,word,dword ?"
Отправлено NuINu , 13-Май-08 09:44 

>С языком проблем нет, с конструкцией struct знаком.

ну если вы так в этом уверены, тогда смотрите

typedef struct Test1_stru {
  unsigned char  byte;
  unsigned short int word;
  unsigned int   dword;
} __attribute__((__packed__)) Test1 ;

можете типы из glib взять, они переносимы и не зависят он архитектуры и компилятора.

>
>Про то где хранить байт,слово, двойное слово и как выделять их из
>массива байт вы не сказали не слова ( имхо вопрос не
>раскрыт.

Вы случаем преподавателем не работаете?


"куда пихать byte,word,dword ?"
Отправлено Ivanoff , 13-Май-08 10:27 
>typedef struct Test1_stru {
>  unsigned char  byte;
>  unsigned short int word;
>  unsigned int   dword;
>} __attribute__((__packed__)) Test1 ;
>
>можете типы из glib взять, они переносимы и не зависят он архитектуры
>и компилятора.

спасибо )

>Вы случаем преподавателем не работаете?

нет, с чего вы взяли?



"куда пихать byte,word,dword ?"
Отправлено anonymous , 13-Май-08 11:09 
>[оверквотинг удален]
>ну если вы так в этом уверены, тогда смотрите
>
>typedef struct Test1_stru {
>  unsigned char  byte;
>  unsigned short int word;
>  unsigned int   dword;
>} __attribute__((__packed__)) Test1 ;
>
>можете типы из glib взять, они переносимы и не зависят он архитектуры
>и компилятора.

Ага, а теперь начинается веселье.  Никто из вас двоих никогда не слышал такой термин как "порядок байтов"?  Little endian, big endian?  Что тот самый short можно передавать двумя байтами в разном порядке следования этих байтов в сетевом потоке?  И у разных машин в памяти он хранится по-разному?  И что читая/передавая такую структуру _напрямую_ вы заново изобретаете ту проблему, которая уже была решена на заре изобретения сетей?


"куда пихать byte,word,dword ?"
Отправлено NuINu , 13-Май-08 14:16 
> Никто из вас двоих никогда не
>слышал такой термин как "порядок байтов"?  Little endian, big endian?
> Что тот самый short можно передавать двумя байтами в разном
>порядке следования этих байтов в сетевом потоке?  И у разных
>машин в памяти он хранится по-разному?  И что читая/передавая такую
>структуру _напрямую_ вы заново изобретаете ту проблему, которая уже была решена
>на заре изобретения сетей?

Давайте уважаемый, без излишних обобощений и огульных обвинений. ничего щас не начнется.
Здесь нигде не рассматривался механизм передачи по сети.


"куда пихать byte,word,dword ?"
Отправлено anonymous , 13-Май-08 18:27 
>Давайте уважаемый, без излишних обобощений и огульных обвинений. ничего щас не начнется.
>
>Здесь нигде не рассматривался механизм передачи по сети.

Извините, если ответил грубо.

Просто у OP изначально была такая конструкция:
cout << "Body: " << buff[3]*100+buff[4]*100+buff[5]*10+buff[6] << endl;
То есть, у него была избыточная система счисления с основанием 10 и 256-ю цифрами (при условии, что первый коэффициент -- 1000, а не 100).  Каждая цифра передавалась одним байтом.

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

Если же писать/читать напрямую структуры, то:
* во-первых, прочитав число таким образом, мы не получим тот же результат, что и при чтении способом из исходного сообщения;
* во-вторых та самая проблема с порядком байтов.

Нужно было не показать, что можно читать/писать структуры, а рассказать, что в настоящих программах делают так:
1. выделить кусок памяти под пакет;
2. функциями htons(), htonl() перевести числа из локального порядка байтов в сетевой;
3. при помощи memcpy() переписать эти числа побайтово в выделеную память начиная с нужного байта;
4. отправить пакет.

1. получить пакет;
2. функцией memcpy() переписать данные из пакета в переменные соответствующего числового типа;
3. функциями ntohs(), ntohl() перевести числа из сетевого порядка байтов в локальный.


"куда пихать byte,word,dword ?"
Отправлено NuINu , 14-Май-08 12:23 
>>Давайте уважаемый, без излишних обобощений и огульных обвинений. ничего щас не начнется.
>>
>>Здесь нигде не рассматривался механизм передачи по сети.
>
>Извините, если ответил грубо.

извиняю :), очень приятно иметь дело с вежливым человеком.

>
>Просто у OP изначально была такая конструкция:
>cout << "Body: " << buff[3]*100+buff[4]*100+buff[5]*10+buff[6] << endl;
>То есть, у него была избыточная система счисления с основанием 10 и
>256-ю цифрами (при условии, что первый коэффициент -- 1000, а не
>100).  Каждая цифра передавалась одним байтом.
>
>Эта конструкция хотя бы не была машинно-зависимой, она вычислится одинаково при любом
>порядке байтов в машине.
>

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

>Если же писать/читать напрямую структуры, то:
>* во-первых, прочитав число таким образом, мы не получим тот же результат,
>что и при чтении способом из исходного сообщения;

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


>[оверквотинг удален]
>
>3. при помощи memcpy() переписать эти числа побайтово в выделеную память начиная
>с нужного байта;
>4. отправить пакет.
>
>1. получить пакет;
>2. функцией memcpy() переписать данные из пакета в переменные соответствующего числового типа;
>
>3. функциями ntohs(), ntohl() перевести числа из сетевого порядка байтов в локальный.
>

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

занимается человек, и пусть себе занимается.


"куда пихать byte,word,dword ?"
Отправлено anonymous , 14-Май-08 17:47 
>На мой взгляд, судя по совокупности ошибок, это никакая не избыточная система
>счисления, а просто еще одна ошибка.
>Но писать код на си, и составлять байтики туда сюда, моделируя некие
>системы счисления не используюя встроенных типов это просто глупо. Помоему не
>надо никакой машинной независимости... программист работая на си должен быть отвлечен
>от порядка байт, в котором храняться слова и др типы. для
>того он и разрабатывался этот си, что бы уйти от ассеблера.

Иногда в общем приходится.  Да и по сути, сами hton*() именно так могут быть реализованы (наложение битовой маски и сдвиг для выделение байтов, и потом сдвиг и объединение по ИЛИ выделенных байтов в нужном порядке).  В заголовках на моей системе, если компилятор GCC, то используется ассемблерная вставка с инструкцией bswap, а если не GCC -- то эти самые сдвиги.

>>Если же писать/читать напрямую структуры, то:
>>* во-первых, прочитав число таким образом, мы не получим тот же результат,
>>что и при чтении способом из исходного сообщения;
>
>не совсем понял что значит прочитать число таким образом?

Если из одного и того же потока прочитать структуру и прочитать тем методом, который был в исходном сообщении, результаты не совпадут (не из-за порядка байтов, а из-за "десятичной" системы счисления).  В принципе, если умножение на 10 это таки ошибка, то вопросов нет.  А вдруг у него какой-то странный протокол?..

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

:)


"куда пихать byte,word,dword ?"
Отправлено Аноним , 14-Май-08 19:26 
>программист работая на си должен быть отвлечен
>от порядка байт, в котором храняться слова и др типы. для
>того он и разрабатывался этот си, что бы уйти от ассеблера.

Нет. C - высокоуровневый ассемблер. Хотите ни о чем не думать - используйте более другие языки.


"куда пихать byte,word,dword ?"
Отправлено NuINu , 15-Май-08 14:16 
>>программист работая на си должен быть отвлечен
>>от порядка байт, в котором храняться слова и др типы. для
>>того он и разрабатывался этот си, что бы уйти от ассеблера.
>
>Нет. C - высокоуровневый ассемблер. Хотите ни о чем не думать -
>используйте более другие языки.

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

си всеже другое дело.


"куда пихать byte,word,dword ?"
Отправлено Аноним , 16-Май-08 19:19 
>ну а я не согласен :) Ассемблер высокоуровневый это вот макроассемблер.

Назовешь принцыпиальное отличие?

Макроассемблер + набор одинаковых макросов под разные архитектуры - вот тебе кроссплатформенность. После можно и оптимизатор прикрутить. Вот тебе и C.

А на C можно отключить оптимизацию и напихать в функции ассемблерных вставок - вот тебе непортабельный ассемблер.


"куда пихать byte,word,dword ?"
Отправлено NuINu , 19-Май-08 10:11 
>>ну а я не согласен :) Ассемблер высокоуровневый это вот макроассемблер.
>
>Назовешь принцыпиальное отличие?
>

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

>Макроассемблер + набор одинаковых макросов под разные архитектуры - вот тебе >кроссплатформенность.

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

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

>После можно и оптимизатор прикрутить. Вот тебе и C.
>
>А на C можно отключить оптимизацию и напихать в функции ассемблерных вставок
>- вот тебе непортабельный ассемблер.

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


"куда пихать byte,word,dword ?"
Отправлено Аноним , 21-Май-08 21:24 
>Лингвистическое. Другой уровнень абстракции. Полное абстрагирование от архитектуры
> физической реализации процессора целевой системы. нет таких понятий как регистр,
> стек. хотя понятия памяти

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

> ну да, охота ваять собственный язык?

Речь идет об устройстве существующих языков.

> Макросы не переносимы. зачастую невозможно создать

Это решается введением стандарта как в C

> рутинных операций, при этом ни вкоем случае не создается архитектурно независимый код.

Повторяю, сделай макросы для всех поддерживаемых архитектур с одним и тем же интерфейсом. Будешь на таком макроассемблере писать кроссплатформенный код. Или ты думаешь gcc магически-автоматически генерирует код под любые архитектуры?

> И самое главное, глупо программировать на ассемблере не используя архитектурных
> особенностей процессора

О том, как надо писать, речи вообще не идет. Речь идет о том что C - высокоуровневый ассемблер.


"куда пихать byte,word,dword ?"
Отправлено angra , 22-Май-08 12:54 
Используя вашу логику любой компилируемый язык это высокоуровневый ассемблер. Если вам так удобно обобщать, то это ваше право, в конце концов кому-то вообще удобно нас всех называть обобщать под названием "компутерщик".

"куда пихать byte,word,dword ?"
Отправлено Аноним , 22-Май-08 21:40 
> Используя вашу логику

Это не моя логика.

> любой компилируемый язык это высокоуровневый ассемблер.

Не любой. Между C и C++ есть, например, принцыпиальная разница. В общем google в руки, честно не охото 100 раз говоренное повторять.


"куда пихать byte,word,dword ?"
Отправлено angra , 23-Май-08 01:16 
И что гуглить? Может лично ваши измышления на других сайтах, вы считаете себя настолько популярным и авторитетным источником? Между C и C++ разница есть, но вот с точки зрения _вашей_ логики и то и другое высокоуровневый ассемблер.

"куда пихать byte,word,dword ?"
Отправлено NuINu , 23-Май-08 09:28 
>И что гуглить? Может лично ваши измышления на других сайтах, вы считаете
>себя настолько популярным и авторитетным источником? Между C и C++ разница
>есть, но вот с точки зрения _вашей_ логики и то и
>другое высокоуровневый ассемблер.

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


"куда пихать byte,word,dword ?"
Отправлено Аноним , 14-Май-08 01:14 
Корректно паковать типы данных в байты самому, так гарантированно не будет проблем с переносимостью между компиляторами, с размерами типов данных и порядком байт.

unsigned char buff[7];

buff[0] = byte_var & 0xff;
buff[1] = word_var & 0xff;
buff[2] = (word_var << 8) & 0xff;
buff[3] = dword_var & 0xff;
buff[4] = (dword_var << 8) & 0xff;
buff[5] = (dword_var << 16) & 0xff;
buff[6] = (dword_var << 24) & 0xff;

byte_var = buff[0];
word_var = buff[1] | ((word)buff[2] << 8));
dword_var = buff[3] | ((dword)buff[4] << 8)) | ((dword)buff[5] << 16)) | ((dword)buff[6] << 24));

word и dword - ваши типы для word и dword соответственно. Обычно нет смысла использовать для обоих что-либо отличное от (unsigned)int.

Кстати в такой структуре:

typedef struct Test1_stru {
  unsigned char  byte;
  unsigned short int word;
  unsigned int   dword;
} __attribute__((__packed__)) Test1 ;

поля лучше хранить в обратном порядке (самые широкие в начале), а все эти __attribute__((__packed__)) - ересь


"куда пихать byte,word,dword ?"
Отправлено Olle , 08-Сен-09 15:21 
>[оверквотинг удален]
>unsigned char buff[7];
>
>buff[0] = byte_var & 0xff;
>buff[1] = word_var & 0xff;
>buff[2] = (word_var << 8) & 0xff;
>buff[3] = dword_var & 0xff;
>buff[4] = (dword_var << 8) & 0xff;
>buff[5] = (dword_var << 16) & 0xff;
>buff[6] = (dword_var << 24) & 0xff;
>

Скорее всего операция сдвига не << , а >>

unsigned char buff[7];

buff[0] = byte_var & 0xff;
buff[1] = word_var & 0xff;
buff[2] = (word_var >> 8) & 0xff;
buff[3] = dword_var & 0xff;
buff[4] = (dword_var >> 8) & 0xff;
buff[5] = (dword_var >> 16) & 0xff;
buff[6] = (dword_var >> 24) & 0xff;


"куда пихать byte,word,dword ?"
Отправлено vvvua , 14-Май-08 11:21 
Определиться нужно с порядком байт, формировать структуру и передавать.
Не забівать про то, что компилятор в сруктурах использует выравнивание. Т.е. sizeof(структура) может быть != сумме sizeof всех типов ее членов.
Вообще, есть на gamedev.ru примеры.
Если и клиент и сервер на полностью одинаковых операционке и архитектуре - можно формировать структуру, отсылать ее без конвертации и так же принимать.


"куда пихать byte,word,dword ?"
Отправлено аноним , 14-Май-08 19:39 
тут кто-то скажет медленно... но лучше конечно snprintf(str, 80, "%d %d %d\n", a, b, c) а на той стороне как получаем строку -- сразу же sscanf(str, " %d %d %d", &a, &b, &c). а про типы отличные от инта забить ))

зы. отцы говорят самый лучший (и самый кроссплатформенный) способ обойти LE/BE и т.п. проблемы - юзать символьные потоки. и в отладке проще будет.


"куда пихать byte,word,dword ?"
Отправлено Аноним , 14-Май-08 20:55 
>зы. отцы говорят самый лучший (и самый кроссплатформенный) способ обойти LE/BE и
>т.п. проблемы - юзать символьные потоки. и в отладке проще будет.

Не бывает `самого' кроссплатформенного. Бывает кроссплатформенный и нет. Поток цифр нисколько не удобней в отладке чем поток байтов.

Вообще, и в XML запихнуть никто не мешает. Только надо сначала головой подумать, что больше подходит, а тем, кто слушает `отцов' эту голову оторвать за ненадобностью.


"куда пихать byte,word,dword ?"
Отправлено аноним , 17-Май-08 03:04 
ну вот сразу и прям так. просто предложил...