socket, парсить пакет
![]() |
Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
|
| ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
| [216.73.217.37] |
|
|
Соблюдайте общие правила форума
MSDN Library
FAQ раздела
Поиск по разделу
Как правильно задавать вопросы| Страницы: (2) [1] 2 все ( Перейти к последнему сообщению ) |
socket, парсить пакет
|
Сообщ.
#1
,
|
|
|
|
всем привет!
пытаюсь научиться адекватно парсить пакеты, нужно что-то на подобии этого чтобы получилось ![]() ![]() ![]() MyType = packed record UID: Dword; NickLen: byte; Nick: String; Other: Byte; end; PMyType = ^MyType; ..................................... var t : PMyType; buf : TByteArray; begin buf:=''; //тут данные t := PMyType(@buf[0]); len:=t^.NickLen; SetString ( nick ,pchar(@t.Nick),len); Nick - имеет разную длину, она в переменной LEN выше способ все парсит но когда я получаю "Other" то он выдает байт не после строки как мне нужно, а выдает 4-ый байт с начала строки =( подскажите как мне правильно парсить пакеты, в идеале надо как на скриншоте чтоб вышло |
|
Сообщ.
#2
,
|
|
|
|
Так объявлять структуру данных для приема пакета (а также для чтения из файла или записи) нельзя, т.к. string - динамический тип - указатель на данные. (В частности, поэтому 4-й байт выдается - размер указателя).
Так что приведение PMyType(@buf[0]) здесь не к месту. Поскольку смещение полей непостоянно, придется использовать, например, PByteArray(@buf[0]), и отдельные поля по текущим смещениям вычленять. |
|
Сообщ.
#3
,
|
|
|
|
+1 к MBo
Держи две полезняшки, пригодятся ![]() ![]() // Чтение данных из буфера. Копирует ByteCount байт из Src в Dest и передвигает Src procedure ReadBytes(var Src: PByte; var Dest; ByteCount: Integer); begin Move(Src^, Dest, ByteCount); Inc(Src, ByteCount); end; // Запись данных в буфер. Копирует ByteCount байт из Src в Dest и передвигает Dest procedure WriteBytes(const Src; var Dest: PByte; ByteCount: Integer); begin Move(Src, Dest^, ByteCount); Inc(Dest, ByteCount); end; Юзать: PBuf := @Buf[0]; ReadBytes(Msg.Type, SizeOf(Msg.Type)); ReadBytes(Msg.Unk, SizeOf(Msg.Unk)); ReadBytes(Msg.UID, SizeOf(Msg.UID)); ... Со строками так не получится, читай про них в хелпе |
|
Сообщ.
#4
,
|
|
|
|
спасибо за ответ!
Цитата Юзать: PBuf := @Buf[0]; ReadBytes(Msg.Type, SizeOf(Msg.Type)); ReadBytes(Msg.Unk, SizeOf(Msg.Unk)); ReadBytes(Msg.UID, SizeOf(Msg.UID)); ... Со строками так не получится, читай про них в хелпе тоесть тоже не подходит для строк ил это комментарий к первому посту?? я так понял тут PBuf : PByteArray; но как его юзать все же не понял так как там уже msg.type ReadBytes(Msg.Type, SizeOf(Msg.Type)); |
|
Сообщ.
#5
,
|
|
|
|
Ну я брал за основу таблицу, которую ты выложил.
Строки надо будет сначала сделать нужной длины, а потом считывать в адрес первого символа. Причем еще учесть, что строки д.б. однобайтовые (для Delphi 2009+ - AnsiString) Добавлено Цитата AHTOLLlKA @ я так понял тут PBuf : PByteArray; PBuf - это просто указатель на буфер байт, имеет тип PByte. |
|
Сообщ.
#6
,
|
|
|
|
![]() ![]() PBuf := @Buf[0]; ReadBytes(Msg.Type, SizeOf(Msg.Type)); не могу понять, если данные в PBuF то как их передать в ReadBytes ? =( ни разу не встречался с ![]() ![]() var Src: PByte; var Dest; смысл понимаю но как правильно сделать не догоняю, подскажите Добавлено ![]() ![]() PBuf,dd: PByte; begin buf:=AnsiStringToByteArray(('01000049B6930C1B042E04110440004200400022041E0421041A04')); PBuf := @buf[0]; ReadBytes(PBuf , dd, 12); memo2.lines.add(pchar(@dd)); вернул - 0100:049B6™ и вывалилась ошибка, почему так?( |
|
Сообщ.
#7
,
|
|
|
|
>и вывалилась ошибка, почему так?(
Потому что под содержимое dd не выделена память |
|
Сообщ.
#8
,
|
|
|
|
![]() ![]() function AnsiStringToByteArray(aString : AnsiString) : TByteArray; var len : integer; begin len := Length(aString); if len > 0 then begin SetLength(result, len); MoveMemory(@result[0], @aString[1], len); end; end; выделяет память, можете поделиться простым кодом чтобы скопировать байты из одного TByteArray в другой TByteArray с длиной и в первоночальном TByteArray удалить их (то что скопировано) |
|
Сообщ.
#9
,
|
|
|
|
функция AnsiStringToByteArray практически бессмысленная. Копировать байты из одного TByteArray в другой, да еще удалять -тоже странное.
Лучше вернуться к реальной задаче. Нужно заполнить структуру MyType? Исходные данные где хранятся? |
|
Сообщ.
#10
,
|
|
|
|
данные хранятся в TByteArray
нужно из src в которой - 01 02 03 04 05 в dest положить 01 02 (первые например два байта) и из src удалить эти первые два байта чтобы он стал - 03 04 05 вот делаю так Код: ![]() ![]() var src,dest: TByteArray; setlength(dest,6); MoveMemory( @dest[0], @src[0], 6); все отлично, но как удалить через INC не понимаю ( |
|
Сообщ.
#11
,
|
|
|
|
![]() ![]() var src,dest: TByteArray; srcindex, destindex: Integer; begin setlength(dest,6); srcindex := 0; destindex := 0; Move(src[srcindex], dest[destindex], 2); Inc(srcindex, 2); //сместили индекс источника, теперь можно продолжать копировать с нового места |
|
Сообщ.
#12
,
|
|
|
|
![]() ![]() Inc(srcindex, 2); //сместили индекс источника, теперь можно продолжать копировать с нового места тут что то не так) Inc(src[srcindex], 2); если так то он меняет этот символ на +2 =( |
|
Сообщ.
#13
,
|
|
|
|
разницы не видишь между тем, что у меня, и у тебя написано?
|
|
Сообщ.
#14
,
|
|
|
|
![]() ![]() var src,dest: TByteArray; srcindex, destindex: Integer; begin src:=AnsiStringToByteArray(HexToString('01000049B6930C1B042E04110440004200400022041E0421041A04')); setlength(dest,4); srcindex := 0; destindex := 0; Move(src[srcindex], dest[destindex], 4); Inc(srcindex, 2); //сместили индекс источника, теперь можно продолжать копировать с нового места memo2.lines.add(String2Hex(ByteArrayToAnsiString(dest))); memo2.lines.add(String2Hex(ByteArrayToAnsiString(src))); на выходе 01000049 01000049b6930c1b042e04110440004200400022041e0421041a04 |
|
Сообщ.
#15
,
|
|
|
|
Скопировали 4 байта, они в приемнике.
Раз 4 байта копировали, то и Inc индекса нужно на 4 делать. Новый srcindex будет указывать на байт b6 Если вопрос в удалении - так оно не нужно. |