PDA

Просмотр полной версии : Как грамотно разлепить пакеты?


mOBSCENE
14.01.2010, 23:05
Есть библиотека внедряемая в волкер при запуске и ставящая перехват на connect, send и recv.
C send проблем никаких волкер шлет пакеты по одному с шифрованием проблем никаких.
Вот с recv проблемко, первый раз я расклеивание сделал таким образом при приходе пакета начинается цикл где по одному вытягиваются пакеты по считыванию из первых 2-х байт пакеты размера каждого и по одному расшифровываются и обрабатываются и копируются в другой отведенный для этого буфер, но проблема часто возникает с последним, он частенько проходит не до конца или половина или начало когда как..), я додумался только сделать так, сохранять это начало и ждать следующего пакета чтобы прочитать собственно эту радость до конца и уже добавлять этот кусочек уже к началу новоприбывшего пакета.
На первом сервере на который первый раз писалась эта библиотека было все на удивлению нормально. На днях переделал ее на другой серв, и начались проблемы, ненаю или сервер творчески любит нарезать пакеты, что иногда моя глупая нарезалка тут не справляется, погоду происходит некислое переполнение буфера волкера и он отказывается работать до перезапуска.

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

PS: сори за грамотейство.

Smith
15.01.2010, 00:03
как вариант, отдельным потоком получать пакеты в два этапа (сначала размер потом сам пакет) и складывать в буфер который уже скармливать боту

finomen
15.01.2010, 01:22
про потоки-дельное замечание. а вот боту буфер кормить не надо. пакеты надо обрабатывать на лету. получили->обработали->отдали идем за следующим. поскольку протокол асинхронный - 2 потока: 1 Client->Server, второй Server->Client

xkor
15.01.2010, 16:58
finomen, счтываешь из сокета всё что там есть в буфер, далее извлекаешь по одному из буфера все целые пакеты и удаляешь их из буфера, опять считываешь всё из сокета и добавляешь в буфер, опять извлекаешь все целые пакеты, ну и так далее)
так я делаю в своих последних программах, в пакетхаке у меня было сделано по другому, написал обёртку к recv которая вызывала recv, далее если recv прочем данных меньше чем запрашивалось то снова вызывала её в цикле пока не было прочитано всех данных...

Smith
16.01.2010, 15:11
finomen, счтываешь из сокета всё что там есть в буфер, далее извлекаешь по одному из буфера все целые пакеты и удаляешь их из буфера, опять считываешь всё из сокета и добавляешь в буфер, опять извлекаешь все целые пакеты, ну и так далее)
А как тогда с пакетами у которых начало только пришло, а конец в следующем буфере? Ведь при добавлении следующего буфера начало затрется и пакет потеряется, если это начало сохранять то получается как у автора схема. Или я чего то не так понял?

ЗЫ xkor можно исходник этой обработки...

xkor
16.01.2010, 16:37
procedure TConnection.WriteBuf(var buf; const size: Integer);
var
i: Integer;
begin
if size<=0 then Exit;
i:=Length(fBuf);
SetLength(fBuf,i+size);
Move(buf,fBuf[i+1],size);

ParseBuf;
end;

procedure TConnection.ParseBuf;
var
pck: PFixPck;
begin
pck:=@fBuf[1];
while(Length(fBuf)>=2)and(Length(fBuf)>=pck.size)do begin
try
if pck.size<2 then pck.size:=2;
if isLogin then fBF.bfDecode(pck.id,pck.size-2)
else fCrypt.DecryptGP(pck.id,pck.size-2)
;
ParsePck(pck); // обработка пакета
finally
Delete(fBuf,1,pck.size);
pck:=@fBuf[1]; // может и не надо но не помешает...
end;
end;
end;

mOBSCENE
05.02.2010, 23:00
Пришлось отказаться от перехвата send и recv и сделать по нормальному на прослойке сервера и клиента на неблокирующем сокете на событиях, а принцип разлепливания пакетов оставил тот же практически, не дошедший пакет накапливается в буфере, как придет до конца, потом обрабатывается и скармливает волкеру частями по 550h.
Работает зараза на удивление не плохо.))