PDA

Просмотр полной версии : разбор пакетов


Elecktron
10.12.2011, 21:52
кто как реализует разбор пакетов?
мне пока что в голову ничего лучше не приходит (кусок исходника джава сервера):

switch (opcode)
{
case 0x00:
msg = new Logout();
break;
case 0x0c:
msg = new CharacterCreate();
break;
case 0x0d:
msg = new CharacterDelete();
break;
case 0x12:
msg = new CharacterSelect();
break;
case 0x13:
msg = new NewCharacter();
break;
}

alexteam
11.12.2011, 04:07
ну разве что чтото вроде

type
TParserFunc = procedure .....
var
OpcodesFuncs : array[0..$ff] of TParserFunc;

гдето:
OpcodesFuncs[0] := @Parse_Die;
........
OpcodesFuncs[$DA] := @Parse_exPackets;
........

гдето вместо кейса:

OpcodesFuncs[packet.opcode]();

не си но идея понятна.

Elecktron
10.01.2012, 12:00
с разбором пакетов по ID разобрался.

а как разбить пакет на составляющие? (dword, char, string)
особенно неясно как быть с "секциями" с переменной длиной... (имя, титул персонажа)

supernewbie
10.01.2012, 16:38
Elecktron, формат надо знать, насчёт имён и титулов - это PWideChar так что в конце 00 00

есть там ещё циклы с блоками, дык там тоже всё просто - кол-во итераций пишется где-нить перед самими блоками

Elecktron
10.01.2012, 22:26
спасибо за ответ.
то что ник и титул widechar я вкурсе.
формат пакетов есть.

в лог я записываю вот так:

for (int i=0;i<packet->size;i++)
{
wsprintfA(buf, "%x",packet->data[i]);
stf(buf);
stf(" ");
}

но это весь пакет...

а мне нужно распределять по переменным, с которыми я буду уже работать.

пакет это массив, а переменные не массивы, и как это совместить я немогу понять...

supernewbie
10.01.2012, 22:32
ну как епт, перемещением памяти в переменные
в делфи это делается процедурой Move, в C++ вроде memcopy

Elecktron
11.01.2012, 01:43
memcpy() копирует массив в массив.
а мне нужно кусок массива в DWORD например..
или кусок массива в widestring, причем с четким определением его длины, чтобы потом было понятно с какого места продолжать чтение пакета.
потому что длина отводимая под ник/титул изменяется в пакете в зависимости от количества символов в нике/титуле...
ник/титул добивается нулями до длины 16/32 байта.

alexteam
11.01.2012, 03:04
memcpy() копирует массив в массив.
колво байтиков которые нужно скопировать указать нельзя чтоле ? да и не масив в масив, а кусок данных.
а мне нужно кусок массива в DWORD например..
и ? 4 байтика скопировать ? в чем трабл ?
или кусок массива в widestring
перебираем массив парами (word)
пока не наткнемся на 0. считаем колво.
алокейтим строку, копируем байтики.
ник/титул добивается нулями до длины 16/32 байта.
пох на длину вайдстринга в пакете.
тебе нужна пара нулей. (выше писали)

supernewbie
11.01.2012, 03:29
перебираем массив парами (word)
пока не наткнемся на 0. считаем колво.
алокейтим строку, копируем байтики.
кстати додумался как круче делать - string(pchar(@pck[байт с которого идёт строка]));
кто-нить видит подводные камни?

Elecktron
11.01.2012, 03:29
колво байтиков которые нужно скопировать указать нельзя чтоле ? да и не масив в масив, а кусок данных.

про количество я вкурсе. я не понял как вытащить кусок не сначала, например с пятого по восьмой..

перебираем массив парами (word)
пока не наткнемся на 0. считаем колво.
алокейтим строку, копируем байтики.

ок. попробую..

Morfik
11.01.2012, 04:36
кстати додумался как круче делать - string(pchar(@pck[байт с которого идёт строка]));
кто-нить видит подводные камни?
widestring(pwidechar(@pck[байт с которого идёт строка]));
или
string(PWideToString(pwidechar(@pck[байт с которого идёт строка])));

хотя я делал так
widestring(pwidechar(Pointer(DWORD(ppck)+[байт с которого идёт строка]))));
string(PWideToString(pwidechar(Pointer(DWORD(ppck) +[байт с которого идёт строка]))));
где ppck это адрес пакета


function PWideToString(pw: PWideChar): string;
var
p: PChar;
iLen: integer;
begin
iLen := lstrlenw(pw) + 1;
GetMem(p, iLen);
WideCharToMultiByte(CP_ACP, 0, pw, iLen, p, iLen * 2, nil, nil);
Result := p;
FreeMem(p, iLen);
end;

supernewbie
11.01.2012, 04:42
дык щас же string=widestring и pchar=pwidechar

Morfik
11.01.2012, 04:45
supernewbie, ну а это смотря а какой делфе говорить, я на 7й доси

supernewbie
11.01.2012, 04:46
Morfik, фуууу, срочно перебегай на xe2, там всякие чёткие списочки добавились, типо TList'а, который умеет хранить любой тип, и такая же хэш таблица
ах да, самое главное та, можно аллочить 8 гб памяти!!111рас

alexteam
11.01.2012, 04:51
фуууу
сам такой.

типо TList'а, который умеет хранить любой тип
он поинтеры хранить всегда умел.

можно аллочить 8 гб памяти
эт только тебе надо.

supernewbie
11.01.2012, 04:52
alexteam, а хеш таблица?
TЧетоТам<string,integer> - ахрененно же

mira
11.01.2012, 11:44
кстати додумался как круче делать - string(pchar(@pck[байт с которого идёт строка]));
кто-нить видит подводные камни?

да. для делфи7 это будит тока первый символ ибо пчар это пансичар.

Elecktron
11.01.2012, 13:49
у меня почему-то работает только такая конструкция:
char buf[1024];
for (int i=0;i<packet->size;i++)
{
wsprintfA(buf, "%x",packet->data[i]);
stf(buf); //сохраняем в лог файл
stf(" "); // пробел :)
}

а хотелось бы как-то так:
charid[i]=packet->data[i];
где я косячу?

xkor
11.01.2012, 20:02
Elecktron, кури работу с указателями и преобразования типов
если память не изменяет по операторам С++, то будет как то так:
charid=*(int *)&(packet->data[i]);

Elecktron
12.01.2012, 05:44
спасибо помогло...

правда теперь другая проблема - вылетает в вечный цикл..

for (int i=0;i<packet->size;i++)
{
buf[i]=*(char *)&(packet->data[i]);
}

Demion
12.01.2012, 13:04
Ну так посмотри какое значение в packet->size и какое значение принимает i. Кроме того не вижу смысла преобразовывать байт в чар. Если нужно копировать в ворд (2байта) либо в дворд (4байта), то можно еще так -
memcpy(&d, buf+i, sizeof(int));
или так -
d = *(int*)(buf+i);

n1ghtmare
12.01.2012, 23:52
спасибо помогло...

правда теперь другая проблема - вылетает в вечный цикл..

for (int i=0;i<packet->size;i++)
{
buf[i]=*(char *)&(packet->data[i]);
}
Проверь свой size и что за бред это: *(char *)&(packet->data[i])
Не проще написать просто packet->data[i]

Edit: да и вообще ты копируеш кусок памяти по сути, нужно memcpy юзать здесь, это и быстрее и правильнее.

Elecktron
15.01.2012, 00:27
разобрался и заюзал это:
memcpy(&d, buf+i, sizeof(int));