-
> Как это "сама удаляет" ?
> Св-во Data - это нетипизированный указатель, откуда серверу
> знать что за ним кроется и как это "удалять" ?
>
>
согласен с вами :) , память почищу при дисконнекте методом destroy если не ошибаюсь, но думаю проблему это не решит
-
> TMyData = class //индивидуальные данные каждого коннекта
> public
> id:integer;//
> logg:boolean;//
> xxx : integer;
> Name : string; // а это что ?
> end;
-
procedure TForm1.servCommandHandlers0Command(ASender: TIdCommand);
//Name это имя юзера оно заполняется при авторизации
Tmydata(asender.Context.Data).name:=asender.Params[0];
-
в [18] приведен полный код обработчика команды.
Что-то я в упор не вижу там ни единого обращения к св-ву Name ..
-
procedure TForm1.servCommandHandlers0Command(ASender: TIdCommand);
begin
q.SQL.Text:='select ID,XXX,B from client where nikname=:ni and pass=:pa';
q.Params[0].Value:=asender.Params[0];
q.Params[1].Value:=asender.Params[1];
q.Open;
if not q.Eof then
begin
asender.Response.Add('USERDATA '+intToStr(Q.Fields[1].value)+' '+intToStr(q.Fields[2].value));
Tmydata(asender.Context.Data).id:=Q.Fields[0].value;
Tmydata(asender.Context.Data).xxx:=Q.Fields[1].value;
Tmydata(asender.Context.Data).logg:=true;
Tmydata(asender.Context.Data).name:=asender.Params[0]; // это было добавлено чуть позже... а скопировалось из старого кода
memo1.Lines.Add('Login '+asender.Params[0]+'='+Tmydata(asender.Context.Data).ip);
end else
begin// user not found
asender.Response.Add('USERNULL 0');
end;
end;
-
> в этом же цикле я добавляю имя клиента в Memo
for i:=0 to list.count-1 do
begin
q.params[0].asinteger:=TMyData(TIdContext(List.Items[i]).Data).xxx; // !!!
...
Memo1.lines.add(q.params[0].asinteger); // какое же это "имя клиента", если ты САМ сказал что имя клиента хранится в св-ве Name, а не в порно-свойстве ?
end;
-
Memo1.lines.add(q.params[0].asinteger) - это дописывал от руки (полного кода с собой нет, поэтому ошибся
Memo1.lines.add(TMyData(TIdContext(List.Items[i]).Data).name); //это отладочная строка, потом будет удалена..
-
т.е. ты утверждаешь что значения порносвойства xxx и св-ва Name в каждом объекте класса TMyData одинаковы и содердат имя клиента ?
-
for i:=0 to list.count-1 do
begin
q.params[0].asinteger:=TMyData(TIdContext(List.Items[i]).Data).xxx; //это порносвойство будет хранить количество коннектов :) этого клиента
q.params[1].asinteger:=TMyData(TIdContext(List.Items[i]).Data).id;
q.ExecSQL;
Memo1.lines.add(TMyData(TIdContext(List.Items[i]).Data).name); //это отладочная строка, потом будет удалена..
end;
xxx и name даже разного типа и содержат разную инфу
-
а где у тебя в обработчике servDisconnect() протоколирование имени отключившегося клиента ?
не вижу ..
-
в [8] писал, что не сделал этого еще, но пока это не важно... я сам знаю, что я отключил Васю, почему Count не уменьшается вот это не понятно
-
при отключении юзера ставить флаг неактивности в его блоке данных.
при обработке листа учитывать значение флага.
локлист и анлок лист поместить в try/finally
-
> я сам знаю, что я отключил Васю
А я вот не знаю что отключил ты именно Васю.
Предлагаешь верить тебе на слово и прочим чудесам ?)
> почему Count не уменьшается
Как это не уменьшается, если
> подключился второй.. третий
> при отключении второго юзера (из трех) count становится равным 2
?
И не уменьшаться он НЕ может, если неопровержим факт возникновения события сервера OnDisconnect
-
> Медвежонок Пятачок © (13.10.11 09:16) [31]
>
> при отключении юзера ставить флаг неактивности в его блоке
> данных.
Он нафих не нужен - с тем же успехом для этого достаточно проанализировать LockedList.Connection.Connected.
-
> Медвежонок Пятачок
К тому же автор утверждает что 2-й клиент из 3-х активных отключился еще при царе горохе - аж час назад,- и в течение часа список контекстов якобы не уменьшился.. Якобы как был равен 3-м, так и остался .. А этого не м.б. если при отключении 2-го клиента на сервере гарантированно возникло и было успешно обработано событие OnDisconnect.
Потому что
procedure TIdContext.AfterRun;
begin
if Assigned(OnAfterRun) then begin
OnAfterRun(Self);
end;
if FContextList <> nil then begin
FContextList.Remove(Self);
end;
end;
-
> требуется переодически сохранять данные о каждом юзере в
> базу данных
Непонятная вообще затея..
Для каждого коннекта сервер в ходе его обслуживания возбуждает кучу всякоразных событий, в контексте обработки которых можно легко и без выкрутасов с общим списком коннектов отреагировать на изменение состояния контекста этого коннекта.
-
вот весь код который работает также... ничего не поменялось, исправил все что советовали, список юзеров вывел в отдельный листбокс, в мемо1 идет лог коннектов и дисконнектов с отображением имени клиента
ЧТО ТУТ НЕ ТАК ?
procedure TForm1.servConnect(AContext: TIdContext);
begin
memo1.Lines.Add('Connect='+Acontext.Connection.Socket.Binding.PeerIP);
acontext.Data:=TmyData.Create;
Tmydata(AContext.Data).logg:=false;
Tmydata(AContext.Data).name:='-';
end;
procedure TForm1.servDisconnect(AContext: TIdContext);
begin
memo1.Lines.Add(Tmydata(AContext.Data).name+' Disconnect='+Acontext.Connection.Socket.Binding.PeerIP+' / '+DateTimeToStr(now));
Tmydata(AContext.Data).Free;
AContext.Data:=nil;
end;
procedure TForm1.servCommandHandlers0Command(ASender: TIdCommand);
begin
q.SQL.Text:='select ID,XXX,B from client where nikname=:ni and pass=:pa';
q.Params[0].Value:=asender.Params[0];
q.Params[1].Value:=asender.Params[1];
q.Open;
if not q.Eof then
begin
asender.Response.Add('USERDATA '+intToStr(Q.Fields[1].value)+' '+intToStr(q.Fields[2].value));
Tmydata(asender.Context.Data).id:=Q.Fields[0].value;
Tmydata(asender.Context.Data).xxx:=Q.Fields[1].value;
Tmydata(asender.Context.Data).logg:=true;
memo1.Lines.Add(asender.Params[0]+' = Login');
Tmydata(asender.Context.Data).name:=asender.Params[0];
end else
begin// user not found
asender.Response.Add('USERNULL 0');
end;
end;
procedure TForm1.Timer1Timer(Sender: TObject);
var i,l,p,verrr:integer;
f:double;
begin
lb1.items.Clear;
if serv.Contexts <> nil then
with serv.Contexts.LockList do try
begin
label1.Caption:=inttostr(count); //здесь на форме смотрю сколько активных юзеров сейчас
q.SQL.Text:='update client set XXX=:dd where id=:id;';
if count>0 then
for i:=0 to count-1 do
begin
if TIdContext(Items[i]).Connection.Connected then
begin
q.params[0].asinteger:=TMyData(TIdContext(Items[i]).Data).rur;
q.params[1].asinteger:=TMyData(TIdContext(Items[i]).Data).id;
q.ExecSQL;
lb1.Items.Add(TMyData(TIdContext(Items[i]).Data).name+' '+inttostr(q.params[0].asinteger));
end else lb1.Items.Add('off '+TMyData(TIdContext(Items[i]).Data).name+' '+inttostr(q.params[0].asinteger));
end;
end;
finally
serv.Contexts.UnlockList;
end;
trans.Commit;//завершаем транзакцию
end;
-
Полные тексты протоколов приведи ..
-
LOGGIN username password //команда авторизации
QUIT // disconnect
:) остальное пока не используется приводить смысла нет, да и остальной протокол еще в разработке
-
ответ на LOGGIN
USERDATA xxx // если авторизация успешна
USERNULL 0 // если авторизация не прошла