-
Спасайте люди добрые :)
пишу клиент-серверное приложение, клиенты общаются с сервером нормально, но требуется переодически сохранять данные о каждом юзере в базу данных,
проблема в следующем- по таймеру 4 раза в минуту выполняется код:
list:=serv.Contexts.LockList;
for i:=0 to list.count-1 do
begin
q.SQL.Text:='update ClientTable set XXX=:dd where id=:id;';
q.params[0].asinteger:=TMyData(TIdContext(List.Items[i]).Data).xxx;
q.params[1].asinteger:=TMyData(TIdContext(List.Items[i]).Data).id;
q.ExecSQL;
end;
serv.Contexts.UnlockList;
это работает если клиент один.... или подключился второй.. третий и т.д... до тех пор пока один из них не отключится. свойство count выдает непонятное число .. оно иногда не меняется при отключении юзера, просто connection помечается как неактивное.
А иногда при отключении второго юзера (из трех) count становится равным 2, а третий юзер на второе место не передвигается... и моя процедура по таймеру пытается постоянно писать в базу данных данные про неактивного второго юзера, а про третьего забывает..
-
> xxx
А это что за порно ?
-
есть блок данных в который записывается id из базы данных о приконнекченом юзере и еще некоторая инфа.... эта инфа переодически меняется клиентским соединением.... и её надо переодически сохранять в базу данных ... если вы знаете более интересный способ, то предложите
-
этот блок данных сохраняется в памяти (структура TMyData) у каждого нового коннекта есть указатель на данные items[i].Data.. вот эти данные в цикле и надо сохранять, так как они очень важные , и ждать, пока клиент через пару дней отвалится... и по дисконнекту сохранять данные не логично...
-
> при отключении второго юзера (из трех) count становится
> равным 2, а третий юзер на второе место не передвигается
С чего он передвинется-то, если ты сделал LockList списку коннектов ?
-
да нет, вы меня не поняли... клиент отключается гораздо раньше чем возникает эта процедура по таймеру, ставил таймер .. раз в 60 секунд.. все равно непонятки возникают. а как бы вы посоветовали считать данные о всех активных подключениях ?
-
> клиент отключается
А как этот фиксирует твой сервер ?
-
в обработчике ондисконнект я вывожу в лог кто отключился... и больше ничего не делаю.. может в этом и ошибка
-
еще при отключении юзера нужно в базу данных сохранить последние актуальные данные, тут надо использовать походу пул коннектов к базе данных, это я еще пока незнаю как сделать
-
> третий юзер на второе место не передвигается
Чкм это подтверждается ?
-
в этом же цикле я добавляю имя клиента в Memo .. и вижу то, что выводится только первый и второй, который уже отключился... а до третьего дело не доходит, так как count уже=2
-
memo1.lines.clear;
q.SQL.Text:='update ClientTable set XXX=:dd where id=:id;';//вынес из цикла
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(q.params[0].asinteger);
end;
-
А оно, это имя, откуда берется ?
Из данных, ссылка на которые ты хранишь в Data ?
Тогда это значит что данные об "имени" клиента не соответствуют действительности
-
именно там и храню, а где их хранить ?? когда создается подключение создается нить... к ней прикрепляется кусок данных, я создаю экземпляр в памяти.. и храню там данные.. когда происходит дисконнект , я очищаю память
-
TMyData = class //индивидуальные данные каждого коннекта
public
id:integer;//
logg:boolean;//
xxx : integer;
Name : string;
end;
-
> когда создается подключение создается нить
На сервере только что случился факт подключения, клиент еще НИЧЕГО не сказал серверу, а сервер уже знает имя клиента ?
Чудеса)..
-
procedure TForm1.servConnect(AContext: TIdContext);
begin
memo1.Lines.Add('Connect='+Acontext.Connection.Socket.Binding.PeerIP+' \ '+DateTimeToStr(now));
acontext.Data:=TmyData.Create;
Tmydata(AContext.Data).logg:=false;
Tmydata(AContext.Data).name:='еще не авторизован';
end;
procedure TForm1.servDisconnect(AContext: TIdContext);
begin
memo1.Lines.Add('Disconnect='+Acontext.Connection.Socket.Host);
end;
это две процедуры когда клиент коннектится, и отключается соответсвенно... в дисконнекте экземпляр данных не уничтожаю.. порылся в исходниках ,. вроде компонента сама удаляет экземпляр данных если он существует ( serv: TIdCmdTCPServer;)
-
нет, авторизация происходит следом за коннектом.. если такого юзера нет.. сразу отключение
-
это обработка команды сервера logging user password
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('Login '+asender.Params[0]+'='+Tmydata(asender.Context.Data).ip);
end else
begin// user not found
asender.Response.Add('USERNULL 0');
end;
end;
-
> в дисконнекте экземпляр данных не уничтожаю.. порылся в
> исходниках ,. вроде компонента сама удаляет экземпляр данных
> если он существует
Как это "сама удаляет" ?
Св-во Data - это нетипизированный указатель, откуда серверу знать что за ним кроется и как это "удалять" ?