Форум программистов, компьютерный форум, киберфорум
C# .NET
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.56/16: Рейтинг темы: голосов - 16, средняя оценка - 4.56
82 / 82 / 24
Регистрация: 30.09.2011
Сообщений: 404
Записей в блоге: 6
1

Маршалинг структур: динамическое управление размером

08.11.2012, 09:52. Показов 3029. Ответов 10
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Решил изучить как с помощью средств c# передавать структуры. Нашел способы преобразования структур в массив байт с помощью Marashal. Вот код структуры:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
[StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Unicode)]
        public struct Package
        {
            public byte pack_type;
            public byte con_status;
            public uint user_id;
            public byte user_status;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
            public string user_name;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
            public string dest_user;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 512)]
            public byte[] buffer;
        }
Собственно вопрос. Так как мне приходится над переменными типа массив указывать их размер, чтобы можно было преобразовать к массиву байт структуру, то получается у меня структура всегда одного и того же размера. Допустим мне надо передать структуру, в которой я только заполню поле pack_type, следовательно все остальное будет пустым, но так как размеры массивов уже предопределены, я отправлю структуру, как бы полностью забитую, а это не очень выгодно, в плане передачи по сети, чем меньше размер пакета, тем лучше. Можно ли строки типа "[MarshalAs(UnmanagedType.ByValArray, SizeConst = 512)]" задавать динамически, во время формирования данных для структуры?
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
08.11.2012, 09:52
Ответы с готовыми решениями:

Маршалинг структур. Размер string
В общем начал разбираться с маршалингом структур. правда некоторые моменты непонятны. например ...

Динамическое создание строки с нужным размером
В C++ есть класс string, который прекрасно создает нужный массив сразу по размеру введенного слова....

Динамическое добавление объектов(структур)
У меня есть класс, который определен как тип...в этом классе я храню информацию о выводимом...

Динамическое размещение массива структур
В коде ниже создается массив из трех структур cs и инициализируется некими значениями. #include...

10
352 / 331 / 49
Регистрация: 12.12.2011
Сообщений: 563
08.11.2012, 14:08 2
Я пользовался примерно таким костылем
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
    public static class StructureMapper
    {
        public static byte[] ToByte(TPacket packet)
        {
            int size = 2 + packet.Length;
            byte[] retVal = new byte[size];
            unsafe
            {
                fixed (byte* ptr = retVal)
                {
                    *((TPacket*)ptr) = packet;
                } 
            }
 
            return retVal;
        }
 
        public static unsafe TPacket ToStruct(byte[] data)
        {
            fixed (byte* pointer = data)
                return *(TPacket*)pointer;
        }
 
        [StructLayout(LayoutKind.Sequential, Pack = 1)]
        public unsafe struct TPacket
        {
            public byte Length;
            public byte OpCode;
            private fixed byte _data[254];
 
            public byte[] Data
            {
                get
                {
                    byte[] retVal = new byte[Length];
                    fixed (byte* ptr = retVal)
                    {
                        for (int i = 0; i < retVal.Length; i++)
                        {
                            retVal[i] = ptr[i];
                        }
                    }
                    return retVal;
                }
                set
                {
                    fixed (byte* ptr = _data)
                        for (int i = 0; i < value.Length; i++)
                        {
                            ptr[i] = value[i];
                        }
                }
            }
        }
    }
1
82 / 82 / 24
Регистрация: 30.09.2011
Сообщений: 404
Записей в блоге: 6
08.11.2012, 14:40  [ТС] 3
Yukikaze, интересный костыль) после такого явно все больше появляется желание писать на плюсах или чистом си передачу структур по сети) Но как я понимаю у меня все равно остается фиксированный массив _data[254]. Я ищу способ примерно такой:
C#
1
2
3
4
5
6
7
8
9
struct S
{
    public byte[] buffer;
}
 
//......где-то в теле метода
S.buffer = new byte[2];
byte[] bytes = StructToByte(S);
//......................................
Добавлено через 13 минут
Изначально я пытался вот таким способом переводить данные структуры в массив байт:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
private byte[] StructToByteArray(packege packet)
        {
            int sizeInBytes = System.Runtime.InteropServices.Marshal.SizeOf(packet);
            Console.WriteLine("Pck size: " + sizeInBytes);
            byte[] outArray = new byte[sizeInBytes];
            MemoryStream stream = new MemoryStream();
            StreamWriter writer = new StreamWriter(stream);
            writer.Write(packet.packet_version);
            writer.Write(packet.packet_type);
            writer.Write(packet.crs32_value);
            writer.Write(packet.result_code);
            writer.Flush();
            return stream.ToArray();
        }
Он работает классно, вот только на стороне сервера не получается распознать принятые данные, точнее если взять и перевести принятые данные в строку, то я получу содержимое структуры, но ведь это надо еще по переменным упаковать....
0
1274 / 975 / 113
Регистрация: 12.01.2010
Сообщений: 1,971
08.11.2012, 15:32 4
если надо передавать данные неизвестного размера придется отправлять их размер вместе с ними
структуру заменить класс, сделать свое преобразование в байты и обратно по своим правилам
1
82 / 82 / 24
Регистрация: 30.09.2011
Сообщений: 404
Записей в блоге: 6
08.11.2012, 15:34  [ТС] 5
m0nax, идею понял, а по поводу

Цитата Сообщение от m0nax Посмотреть сообщение
сделать свое преобразование в байты и обратно
есть примеры? или идеи?
0
1274 / 975 / 113
Регистрация: 12.01.2010
Сообщений: 1,971
08.11.2012, 15:53 6
да все почти так же как в приведенном StructToByteArray, просто перед записью данных записать их размер(это же не SizeOf будет, а руками посчитать)
1
82 / 82 / 24
Регистрация: 30.09.2011
Сообщений: 404
Записей в блоге: 6
08.11.2012, 16:02  [ТС] 7
m0nax, до вот в этом то и проблема щас. Приведу примеры.
Допустим есть структура:
C#
1
2
3
4
5
6
7
public struct packege
        {
            public Int16 packet_version;
            public Int16 packet_type;
            public UInt32 crs32_value;
            public Int16 result_code;
        }
Значение её переменных:
C#
1
2
3
4
pack.packet_version = 28;
pack.packet_type = 2;
pack.crs32_value = 344912;
pack.result_code = 0;
После применения моего метода получаем на выходе, вот такую строку(массив байт):
32383233343439313230
Если отбрасывать приписанные 3-йки перед каждой цифрой то получу строку со своими значениями, остается вопрос как считать? Например. Допустим я избавился от троек, домножив каждый байт(32 - это один байт) на 0x0F, вот теперь проблема в числах. Как их растосовать по переменным, понимаю что 2-йку(тип пакета) не трудно забрать, а вот 28 как вытащить? Я все к тому что число может быть и из 3 цифр и 10, это же ведь надо как то определить. Я пытался считывать из массива байт примерно вот таким образом переменные:
C#
1
pack.packet_version = (short)IPAddress.NetworkToHostOrder(reader.ReadInt16());
Но результат был неправильный. Да он считывал первых два байта, но только как 3238, в 10-ой СС это 12856 получалось.
0
1274 / 975 / 113
Регистрация: 12.01.2010
Сообщений: 1,971
08.11.2012, 16:06 8
Причем тут строка?
есть структура, переводишь ее в байты и отправляешь
на другой стороне получаешь в виде байтов и конвертируешь в структуру
в каком месте тут появилась строка? вместо StreamWriter использовать BinaryWriter...
0
82 / 82 / 24
Регистрация: 30.09.2011
Сообщений: 404
Записей в блоге: 6
08.11.2012, 16:09  [ТС] 9
m0nax, под строкой я имел ввиду массив из байт)))
0
1274 / 975 / 113
Регистрация: 12.01.2010
Сообщений: 1,971
08.11.2012, 16:12 10
просто читай в том же порядке что записывал, числа всегда занимают фиксированный размер поэтому хоть там 2 хоть 3463453456 не имеет значения, это все равно 4 байта (Int) и любой BinaryReader прекрасно это прочитает
1
82 / 82 / 24
Регистрация: 30.09.2011
Сообщений: 404
Записей в блоге: 6
08.11.2012, 16:18  [ТС] 11
m0nax, Заработало) и с string тоже норм работает, не надо даже указывать размер) Спасибо за подсказки, теперь все работает как надо)
0
08.11.2012, 16:18
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
08.11.2012, 16:18
Помогаю со студенческими работами здесь

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

Динамическое управление памятью
Здраствуйте! Уважаемые форумчани немогли бы вы мне помочь с вот такой вот задачей? Сформировать...

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

Динамическое управление компонентами
Пример: Есть форма1 и форма2. Форма1: Компоненты: Окно &quot;мемо&quot; для ввода числа и кнопка....


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
11
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru