Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2005.10.02;
Скачать: CL | DM;

Вниз

Протокол обмена между клиентом и сервером   Найти похожие ветки 

 
Gek1   (2005-05-19 18:07) [40]

pOutArray := pOutData;

Далее в коде уже:
pOutArray^[despos] := -treepos;


 
Digitman ©   (2005-05-19 18:18) [41]


> Gek1   (19.05.05 18:07) [40]


ты не понял.
я спросил, где и как у тебя инициализируется значение указательной переменной PHuffDecompress, которое ты передаешь в ф-цию DecompressNew ?

DecompressNew(fIncomingBuf,PHuffDecompress,PHuffDecompressLen,fIncomingBufLen);

ведь это выходной буфер декомпрессора !
ты же где-то память под него размером выделяешь ?

в твоем коде формирование значения PHuffDecompressLen я вижу, но нигде не вижу чтобы ты выделял память под буфер соотв.размера и записывал его адрес в переменную PHuffDecompress перед тем как передать ее параметром в ф-цию декомпрессии


 
Gek1   (2005-05-19 18:22) [42]


> ведь это выходной буфер декомпрессора !
> ты же где-то память под него размером выделяешь ?


Как и fIncomingBuf - создаю в OnConnect
освобождаю в OnDisconnect
при этом тамже сбрасываю их длинны на ноль.

Размер буфферов 50к и 150к.


 
Digitman ©   (2005-05-19 18:38) [43]


> Размер буфферов 50к и 150к.


значения от фонаря, надо понимать ...


 
Gek1   (2005-05-20 09:37) [44]


> Digitman ©   (19.05.05 18:38) [43]

Я бы не сказал, что от фоноря...

Взяты были с запасом.

Первый буфер был выбран по непроверенному факту, что длинна пакета не может быть больше 0х8000.
Поэтому взял с запасом и сделал 50к.

Второй (собирающий) буфер (fIncomingBuf) был выбран из расчета густонаселенной местности. Было определен примерный обьем и расчитанно примерно максимально возможное его значение. Все эти подсчеты относительны, но взяты (на всякий пожарный) с запасом.


 
Digitman ©   (2005-05-20 10:27) [45]


> Первый буфер


какой "первый" ? ты оперировать конкретными идентификаторами в своем коде можешь ?


> непроверенному факту, что длинна пакета не может быть больше
> 0х8000


т.е. от балды


> густонаселенной местности


что еще за "местность" ?
какое отношение имеет к алгоритму компрессии/декомпрессии ?


 
Gek1   (2005-05-20 10:35) [46]


> какой "первый" ? ты оперировать конкретными идентификаторами
> в своем коде можешь ?

Могу. первый всмысле TempBuf.


> т.е. от балды

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

Учитывая что сервер не отправляет пакеты по очереди а клеит (перед сжатием) их вместе, в случае если много информации поменялось. Например при коннекте - загружается вся обстановка и все параметры. Идет порядка нескольких десятков различных пакетов. Все они собираються в очередь ... потом сжимаются и отправляются. Из этих расчетов были выбраны буферы.


 
Digitman ©   (2005-05-20 11:12) [47]


> Могу. первый всмысле TempBuf


про TempBuf вообще речи не идет.
вот TempBuf как раз можно и от балды выбрать
но лучше выбрать его кратным 4к

речь же идет о PHuffDecompress, т.е. буфере, в который Хаффман-декомпрессор записывает результат ...


 
Gek1   (2005-05-20 11:24) [48]

PHuffDecompress как и FincomingBuf имееют размер 150к.


> но лучше выбрать его кратным 4к

Это да. не подумал. Сделаю все кратными 4к.


 
Digitman ©   (2005-05-20 11:26) [49]

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


 
Gek1   (2005-05-20 11:29) [50]

Digitman ©   (20.05.05 11:26) [49]
Именно. Иначе данные будут испорчены.
Но как я понял практически всегда первые пару байт получатся правильными.
К сожалению на это мне приходится расчитывать, потому как альтернативы не нашел.


 
Digitman ©   (2005-05-20 11:31) [51]


> первые пару байт получатся правильными


и как ты интерпретируешь и используешь содержимое этих первых 2-х байт ?


 
Gek1   (2005-05-20 11:35) [52]


> и как ты интерпретируешь и используешь содержимое этих первых
> 2-х байт ?

Смотри сам алогритм из [5]

А также ф-цию определения длинны пакета:

function TCharacter.GetPacketLen(PacketObj:PArray; Size : integer) : Integer;
{Ф-ция вернет:
0 если пакет маленький и надо еще кусок
-1 если пакет неизвестный
длинну, если длина >= пакету}
var PacketID : Word;
   PacketLen : Word;
   ResSize : Integer;
const
PacketLengths : array[0..255] of Word =
{Если длинна равна $00, то неизвестный пакет
Если длинна >= $8000 - значит определяем динамическую длинну}
( { $00 } $0068, $0005, $0007, $8000, $0002, $0005, $0005, $0007, $000E, $0005, $000B, $010A, $8000, $0003, $8000, $003D,
{ $10 } $00D7, $8000, $8000, $000A, $0006, $0009, $0001, $8000, $8000, $8000, $8000, $0025, $8000, $0005, $0004, $0008,
{ $20 } $0013, $0008, $0003, $001A, $0007, $0014, $0005, $0002, $0005, $0001, $0005, $0002, $0002, $0011, $000F, $000A,
{ $30 } $0005, $0001, $0002, $0002, $000A, $028D, $8000, $0008, $0007, $0009, $8000, $8000, $8000, $0002, $0025, $8000,
{ $40 } $00C9, $8000, $8000, $0229, $02C9, $0005, $8000, $000B, $0049, $005D, $0005, $0009, $8000, $8000, $0006, $0002,
{ $50 } $8000, $8000, $8000, $0002, $000C, $0001, $000B, $006E, $006A, $8000, $8000, $0004, $0002, $0049, $8000, $0031,
{ $60 } $0005, $0009, $000F, $000D, $0001, $0004, $8000, $0015, $8000, $8000, $0003, $0009, $0013, $0003, $000E, $8000,
{ $70 } $001C, $8000, $0005, $0002, $8000, $0023, $0010, $0011, $8000, $0009, $8000, $0002, $8000, $000D, $0002, $8000,
{ $80 } $003E, $8000, $0002, $0027, $0045, $0002, $8000, $8000, $0042, $8000, $8000, $8000, $000B, $8000, $8000, $8000,
{ $90 } $0013, $0041, $8000, $0063, $8000, $0009, $8000, $0002, $8000, $001A, $8000, $0102, $0135, $0033, $8000, $8000,
{ $a0 } $0003, $0009, $0009, $0009, $0095, $8000, $8000, $0004, $8000, $8000, $0005, $8000, $8000, $8000, $8000, $000D,
{ $b0 } $8000, $8000, $8000, $8000, $8000, $0040, $0009, $8000, $8000, $0003, $0006, $0009, $0003, $8000, $8000, $8000,
{ $c0 } $0024, $8000, $8000, $8000, $0006, $00CB, $0001, $0031, $0002, $0006, $0006, $0007, $8000, $0001, $8000, $004E,
{ $d0 } $8000, $0002, $0019, $8000, $8000, $8000, $8000, $8000, $8000, $010C, $8000, $8000, $0009, $0000, $0000, $0000,
{ $e0 } $0000, $0000, $0000, $0000, $0000, $0000, $0000, $0000, $0000, $0000, $0000, $0000, $0000, $0000, $0000, $0000,
{ $f0 } $8000, $0000, $0000, $0000, $0000, $0000, $0000, $0000, $0000, $0000, $0000, $0000, $0000, $0000, $0000, $0004 );
begin
{Если размер нулевой, то выходим}
if Size = $00 then
   begin
   Result := 0;
   Exit;
   end;
PacketID := PacketObj^[0];
PacketLen := PacketLengths[PacketID];
{Если пакет неизвестный, то вернем - 1}
if PacketLen = $00 then
   begin
   Result := -1;
   Exit;
   end;
{Если динамическая длинна, то посчитаем ее
или выдадим 0 если нехватает данных}
if PacketLen >= $8000 then
begin
if Size > 3 then
   begin
   ResSize := strtoint("$"+IntToHex(PacketObj^[1],2)+IntToHex(PacketObj^[2],2));
   {Если пакет неполный, то выдадим 0}
   if ResSize <= Size then Result := ResSize
   else Result := 0; {if ResSize > Size}
   end
else Result := 0; {if Size < 3}
end
else {Иначе выдаем фиксированную длинну пакета}
   begin
   ResSize := PacketLen;
   {Если пакет неполный, то выдадим 0}
   if ResSize <= Size then Result := ResSize
   else Result := 0; {if ResSize > Size}
   end;
end;


 
Digitman ©   (2005-05-20 13:02) [53]

в [5] - "кошмар" (см. [6])

ГДЕ в [5] интерпретация первых 2-х байт чего-то там ? ткни меня носом ....


 
Gek1   (2005-05-20 13:28) [54]

Вот в этом коде я проверяю блок данных на целостность пакетов:


{Далее проверяем чтобы в буффере было N целых пакетов}
index:=0;
PacketLen := 1; {Любое положительное число}
while (index < PHuffDecompressLen) and (PacketLen > 0) do
begin
New(TempBuf);
for i := 0 to PHuffDecompressLen - (index + 1) do TempBuf^[i] := PHuffDecompress^[i+index];
TempBufLen := PHuffDecompressLen - index;
{Ф-ция GetPacketLen вернет:
0 если пакет маленький и надо еще кусок
-1 если пакет неизвестный
длинну, если длина >= пакету}
PacketLen := GetPacketLen(TempBuf,TempBufLen);
{Освободим TempBuf}
Dispose(TempBuf);
{Если длинна больше нуля, то увеличиваем индекс}
if PacketLen > 0 then index := index + PacketLen;
{Если длинна равна 0, то выходим}
if PacketLen = 0 then Exit;
{Если длинна меньше нуля, то:}
if PacketLen < 0 then
  begin
  {Выдаем ошибку о неизвестном пакете}
  SHex := "";
  for i := index to PHuffDecompressLen - 1 do SHex:= SHex + IntToHex(PHuffDecompress^[i],2);
  AddtoDebugLog(GetCharName+": "+"Внимание! Обнаружен неизвестный пакет: "+SHex);
  {Останавливаем соединение}
  GameClient.Close;
  {Выходим}
  Exit;
  end;
{Если длинна больше $8000, то:}
if PacketLen > $8000 then
  begin
  {Выдаем ошибку о неверной длинне пакета}
  SHex := "";
  for i := index to PHuffDecompressLen - 1 do SHex:= SHex + IntToHex(PHuffDecompress^[i],2);
  AddtoDebugLog(GetCharName+": "+"Внимание! Неверная длинна пакета: "+SHex);
  {Останавливаем соединение}
  GameClient.Close;
  {Выходим}
  Exit;
  end;
{Далее или у нас будет только N целых пакетов
или выйдем ранее из процедуры}
end; {End while (index < PHuffDecompressLen) and (PacketLen > 0)}


 
Digitman ©   (2005-05-20 13:42) [55]


> Gek1   (20.05.05 13:28) [54]


бред какой-то...

какие нафих "пакеты" ? Хаффман не знает никаких "пакетов" !
Хаффман сжимает некий блок инф-ции (ему по барабану, пакеты там или не пакеты), а сервер тебе передает то что выдал Хаффман...

ГДЕ в [54] обращение к тем самым "первым 2-ум байтам" ? ... покажи мне ! ... ткни меня носом ...


 
Eraser ©   (2005-05-20 13:59) [56]

Gek1

Как-то всё в твоём алгоритме перепутано.
Переработай алгоритм, чтобы приём данных осуществлялся так.

1. Чтение первых 4 байт - размер принимаемых данных.
2. Чтение потока данных, размер которых взят из п. 1.
3. Распаковка/дефифровка потока данных считанного из п. 2.

Куда уж проще.


 
Digitman ©   (2005-05-20 14:04) [57]


> Eraser ©   (20.05.05 13:59) [56]


да не знает он ни черта протокол этот..
тычется как слепой котенок .. на основании ОБС ...


 
Gek1   (2005-05-20 14:08) [58]


> Digitman ©   (20.05.05 13:42) [55]

Алгоритм работает так:
1. Принимаю данные
2. Дописываю в конец буфера
3. Расжимаю данные алгоритмом Хаффмана
4. Далее проверяем расжатый блок данных на наличие N целых пакетов. И если там оказывается не полные пакеты, то выходим и ждем пока прийдет новый кусок данных. Смотри [54]
5. Далее (если у нас N целых пакетов):
Обрабатываем каждый пакет и сбрасываем входной буфер на ноль.

Т.е суть алгоритма - принимать во входящий буфер сжатые куски данных, пока после распаковки там не окажется N целых пакетов.


> ГДЕ в [54] обращение к тем самым "первым 2-ум байтам" ?
> ... покажи мне ! ... ткни меня носом ...

В [54] смотри ф-цию GetPacketLen

А в описании этой ф-ции [52]:
PacketID := PacketObj^[0];
Здесь обратилиcь к первому байтику и узнали ID пакета.

Далее в [52] по коду:

{Если динамическая длинна, то посчитаем ее
или выдадим 0 если нехватает данных}
if PacketLen >= $8000 then
begin
if Size > 3 then
  begin
  ResSize := strtoint("$"+IntToHex(PacketObj^[1],2)+IntToHex(PacketObj^[2],2));
  {Если пакет неполный, то выдадим 0}
  if ResSize <= Size then Result := ResSize
  else Result := 0; {if ResSize > Size}
  end
else Result := 0; {if Size < 3}
end


Обрати внимание на:
ResSize := strtoint("$"+IntToHex(PacketObj^[1],2)+IntToHex(PacketObj^[2],2));
Здесь как раз в случае дин. длинны - определяем нужную длину пакета из 2-го и 3-го байта.

Т.е все динамические пакеты имеют один и тот же формат в начале:
· BYTE cmd
· BYTE[2] packet length


 
Gek1   (2005-05-20 14:11) [59]


> Eraser ©   (20.05.05 13:59) [56]

Так не будет работать.
Поток данных может (и очень часто так бывает) содержать несколько пакетов с данными. каждый пакет может в свою очередь иметь дин. длинну, которую мне надо определить, чтобы посчитать полную длинну потока данных.

Проще некуда.


 
Eraser ©   (2005-05-20 14:15) [60]

Gek1   (20.05.05 14:11) [59]

1. Что за сервер? Приведи название программы.
2. каждый пакет может в свою очередь иметь дин. длинну

в TCP впринципе очень сложно формировать каждый пакет по отдельности - свой драйвер ядра для этого писать надо. Так что ты заблуждаешься. Где-то ДОЛЖНА передаваться длина данных... или стоп-последовательность (что врядли).


 
Alexander Panov ©   (2005-05-20 14:18) [61]


> Где-то ДОЛЖНА передаваться длина данных... или стоп-последовательность
> (что врядли).


Возможен еще вариант - каждый запакованный пакет имеет одинаковую длину, определенную разработчиком.


 
Eraser ©   (2005-05-20 14:20) [62]

Alexander Panov ©   (20.05.05 14:18) [61]

Ну или так.
Только терми "пакет" в данном случае лучше не использовать, чтобы путаницы небыло.


 
Digitman ©   (2005-05-20 14:23) [63]


> Gek1   (20.05.05 14:08) [58]



> 1. Принимаю данные


"шматок" данных ты рпринял, а не "данные".


> 2. Дописываю в конец буфера


да на здоровье ..


> 3. Расжимаю данные алгоритмом Хаффмана


какие "данные"-то ? только что принятый "шматок" или N "шматков", принятых ранее + текущий "шматок" ?

разжимать следует не непонятно что, а данные, соответствующие ЦЕЛОСТНОМУ сообщению передатчика !

а размер этого сообщения ты не знаешь !


 
Gek1   (2005-05-20 14:25) [64]


> 1. Что за сервер? Приведи название программы.

Ultima Online
В основном используються POL сервера, поэтому я тестирую на POL095.
Хотя на Sphere глюки тоже были замечены.


> 2. каждый пакет может в свою очередь иметь дин. длинну
>
> в TCP впринципе очень сложно формировать каждый пакет по
> отдельности

Когда я говорил пакет, я имеел ввиду пакет с информацией, посланный самим сервером.
В случае с TCP - я писал TCP пакет.

Например:

0x1A Packet
Object Information (Variable # of bytes)
· BYTE cmd
· BYTE[2] blockSize
· BYTE[4] itemID
· BYTE[2] model #
· if (itemID & 0x80000000)
· BYTE[2] item count (or model # for corpses)
· if (model & 0x8000)
· BYTE Incr Counter (increment model by this #)
· BYTE[2] xLoc (only use lowest significant 15 bits)
· BYTE[2] yLoc
· if (xLoc & 0x8000)
· BYTE direction
· BYTE zLoc
· if (yLoc & 0x8000)
· BYTE[2] dye
· if (yLoc & 0x4000)
· BYTE flag byte (See top)


Вот это пакет 0x1A от сервера. Непутайте с TCP пакетами.


> Где-то ДОЛЖНА передаваться длина данных... или стоп-последовательность
> (что врядли).

В сжатой части длинна не обнаружена и стоп последовательность тоже.

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


 
Gek1   (2005-05-20 14:29) [65]


> Возможен еще вариант - каждый запакованный пакет имеет одинаковую
> длину, определенную разработчиком.

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

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


 
Eraser ©   (2005-05-20 14:29) [66]

Gek1   (20.05.05 14:25) [64]

А где-нибудь есть SDK или описание протокола данной сетевой игрушки.


 
Eraser ©   (2005-05-20 14:32) [67]

Gek1   (20.05.05 14:29) [65]

Вот щас нашёл в сети, где можно скачать клиент, такую надпись

"Без файлов данного архива Вы не сможете играть на сервере. Файлы из данного архива необходимо разархивировать в папку с игрой. В данном архиве следующие файлы: client.exe, abyss.dll."

Скорее всего вся "логика" соединения в этих файлах... уже создана разработчиком сервера.


 
Gek1   (2005-05-20 14:34) [68]


> "шматок" данных ты рпринял, а не "данные".

Да. шмоток ... кусочек ...


> какие "данные"-то ? только что принятый "шматок" или N "шматков",
> принятых ранее + текущий "шматок" ?

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


 
Eraser ©   (2005-05-20 14:36) [69]

Gek1   (20.05.05 14:34) [68]

если в прошлый раз пришел оборваный пакет, то буфер не будет пустым и новый "шматок" допишется к старым "шматкам".


Всё. Я ретируюсь.. ))


 
Gek1   (2005-05-20 14:39) [70]


> А где-нибудь есть SDK или описание протокола данной сетевой
> игрушки.

Если бы было SDK - я бы ВАМ и себе голову не морочил. Давно уже все бы работало. Игрушка старая. Описание протокола закрыто и никому в руки не попадало.
Есть только кодеры, которые потихонечку анализировали и разгадывали как он устроен, но до конца он неизвестен.


> Без файлов данного архива Вы не сможете играть на сервере.
> Файлы из данного архива необходимо разархивировать в папку
> с игрой. В данном архиве следующие файлы: client.exe, abyss.dll."
>
> Скорее всего вся "логика" соединения в этих файлах... уже
> создана разработчиком сервера.

Это ты нашел сам клиент от разрабочиков, только забыл его версию глянуть, так как криптация в них различна.
abyss.dll - на абисе небыл, но многие вставляют dll-ки, которые борятся с любителями искать "багов" в программах.
Сам тоже не люблю любителей "багов", поэтому стараюсь, чтобы они пользоватся ими не могли.


 
Digitman ©   (2005-05-20 14:41) [71]


> Gek1   (20.05.05 14:34) [68]



> Принятый "шматок" дописываю в конец буффера


не возражаю.


> если в прошлый раз пришел оборваный пакет


в ПРОШЛЫЙ раз пришел не "оборваный пакет", а очередной фрагмент неких данных, упакоавнных Хафман-компрессором !!
НИ о каких пакетах НЕ может идти речи, пока "сжатые" данные НЕ "разжаты" !
а чтобы их "разжать" , нужно знать хотя бы длину данных, содержащих "сжатые" данные, перед сжатием представлявшие собой N пакетов


 
Eraser ©   (2005-05-20 14:41) [72]

Gek1   (20.05.05 14:39) [70]

Тогда со сниффером наперевес надо анализировать что там посылается...


 
Gek1   (2005-05-20 14:42) [73]


> Всё. Я ретируюсь.. ))

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


 
Gek1   (2005-05-20 14:48) [74]


> НИ о каких пакетах НЕ может идти речи, пока "сжатые" данные
> НЕ "разжаты" !
> а чтобы их "разжать" , нужно знать хотя бы длину данных,
> содержащих "сжатые" данные, перед сжатием представлявшие
> собой N пакетов

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

Далее клею это фрагмент в конец и расжимаю опять все это дело.
Потом опять анализирую и тд


 
Digitman ©   (2005-05-20 14:50) [75]


> Сам протокол очень сложен


как бы ни был он сложен, но до тех пор пока ты не знаешь те его соглашения, которые ты пытаешься использовать, - грош цена твоему коду, работать он как положено не будет, и затея твоя стоит ГОРАЗДО дороже того что ты предполагал на момент "зачатия"


 
Eraser ©   (2005-05-20 14:51) [76]

Gek1   (20.05.05 14:48) [74]
Ну не передает сервер длинну сжатого блока.


Значит длина пакета строго регламентирована!
Dump снифера многое бы прояснил... может быть.


 
Gek1   (2005-05-20 14:54) [77]


> Значит длина пакета строго регламентирована!
> Dump снифера многое бы прояснил... может быть.

Дамп самого сжатого блока или история длин блоков?


 
Eraser ©   (2005-05-20 14:55) [78]

Gek1   (20.05.05 14:54) [77]
Дамп самого сжатого блока


А есть ещё и несжатый блок? Кстати, как ты определяешь сжатый это блок или нет? )


 
Gek1   (2005-05-20 15:09) [79]


> А есть ещё и несжатый блок? Кстати, как ты определяешь сжатый
> это блок или нет? )

После того как отработает LoginClient ... стартует GameClient и все данные от сервера сжимаються.


 
False_Delirium ©   (2005-05-20 15:13) [80]

http://uo.menatwork.com.ua/files/injection/uoinj.rar

Всё это должно делаться насколько я помню.



Страницы: 1 2 3 вся ветка

Текущий архив: 2005.10.02;
Скачать: CL | DM;

Наверх




Память: 0.66 MB
Время: 0.035 c
1-1126254560
Николай1
2005-09-09 12:29
2005.10.02
Создание отчётов для БД при помощи HTML


4-1123255244
Olimp
2005-08-05 19:20
2005.10.02
Com порт


9-1117624793
Кирилл
2005-06-01 15:19
2005.10.02
Панель задач


1-1126179691
atruhin
2005-09-08 15:41
2005.10.02
Где найти готовую хэш функцию


3-1124258621
PChI
2005-08-17 10:03
2005.10.02
Описание dxdbgrid