各位兄弟姐妹们,小弟有一问题很是头疼。
一CS结构软件,在每个登录者登录后都有一个已登录标记,用来判断不能用同一用户名同时在不同机器上登录,但现在的问题是一旦发生非法退出或是死机等情况后,已登录标记并没有改过来,出现下次不能登录的情况,需要到服务器的数据库里改一下。怎么能判断出非法退出或是死机等情况,把相应的代码写进去呢?
一CS结构软件,在每个登录者登录后都有一个已登录标记,用来判断不能用同一用户名同时在不同机器上登录,但现在的问题是一旦发生非法退出或是死机等情况后,已登录标记并没有改过来,出现下次不能登录的情况,需要到服务器的数据库里改一下。怎么能判断出非法退出或是死机等情况,把相应的代码写进去呢?
在可能出现异常的地方
tryexceptend
楼主好运
tryexceptend
语用在什么地方写啊
从系统表中查询即可
delete mytable where hostname not in(select hostname from master.dbo.sysprocesses)if exists(select * from mytable where operator=@operator)
--表示用户正在登录使用中
如果服务端接到了回应字符,将发回的机器名重新整理就得到新的在线目录
如果是在原目录基础上更新的华(不是CLEAR后重组),如果匹配不上的就显示“机器名+掉线”
例如
query:TADOquery;----try
query:=TADOQUERY.CREATE(NIL);
exceptend
tryexcept
之间吗?
每次client登錄, 驗證後, server 生成一個授權ID分配給 client, 保存在client 中,
然後, Client 每當有關鍵查詢 or 提交時, 必須帶有驗證ID一并提交
类似于浏览网页时的操作超时,可以用 zswangII(伴水清清)的方法解决。
T_LOGINED_USER ( USER_NAME, HOST_NAME )另外设立一个同步表
T_SYNC ( DUMMY )
INSERT INTO T_SYNC VALUES ( 0 );对于每个登录客户,是用3个事务来防止同一用户在不同机器上登陆T1 (在READ COMMITTED级别下)
T2 (READ UNCOMMITTED)
T3 (READ COMMITTED)每一个登陆都依照下面的过程:
T1 START
T1 WRITE (UPDATE T_SYNC SET DUMMY = 0)
T2 START
T2 READ (EXISTS(SELECT * FROM T_LOGINED_USER
WHERE USER_NAME = :USER_NAME AND HOST_NAME = :HOST_NAME))
IF EXISTS T1 COMMIT, T2 COMMIT, ABORT
ELSE CONTINUE
T3 START
T3 INSERT INTO T_LOGINED_USER VALUES (:USER_NAME, :HOST_NAME)
T2 COMMIT
T1 COMMIT SUCCESS(注,不要提交T3)退出登录时,T3 ROLLBACK假锁的情况:当客户端突然丢失连接时,服务器不是马上就知道客户端已经退出,
这里有一段假锁的时间,这段时间里,
因为在T2 READ这一步发现一个记录,用户不能重新登录,
当服务器被通知TCP/IP连接已经异常断开,服务器会回滚T3,
这时用户才可以恢复登录不过这个假锁时间是可以通过WINDOWS设置调整成比较短的,
也有些数据库提供检查事务活动性的功能,这也可以利用,
或者通过管理员,强制尚在活动的T3事务回滚,这样用户就马上可以恢复登录了
顾不上睡午觉,修正一下,其实只用T3一个事务就可以了,
在登录时,INSERT INTO T_LOGINED_USER VALUES (:USER_NAME, :HOST_NAME)
如果有重复记录,肯定触发异常,退出时,rollback T3就行了
T3 INSERT INTO T_LOGINED_USER VALUES (:USER_NAME, :HOST_NAME)
SUCCESS(注,不要提交T3)不知道以上语句要在哪里写,是代码里,还是在触发器里写呢?能具体说说详细的步骤吗,我不太明白,谢谢了!
USER_NAME VARCHAR(32) NOT NULL,
HOST_NAME VARCHAR(64) NOT NULL,
PRIMARY KEY (USER_NAME, HOST_NAME)
);该表不要有任何内容,
登录的时候,单独启动一个事务,然后执行SQL语句
INSERT INTO T_LOGINED_USER VALUES ('用户名', '登录所在机器名')
如果遇到关键字重复的错误,那么说明用户重复登录了
如果没有问题,用户就可以顺利登录这就OK了,
注意是要一直保持这个事务,不要提交它,直到用户注销登录时,
就回滚这个事务
begin
ADOConnection1.BeginTrans ;
try
ADOCommand1.CommandText :='INSERT INTO USER1 VALUES (11,111)';
ADOCommand1.Execute ;
except
'提示出错代码
end;
end;procedure TForm1.Button2Click(Sender: TObject);
begin
ADOConnection1.RollbackTrans;
close;
end;运行后,1.如出错的话Except语句不执行。2.我用同一机器同一用户登录后非法退出,然后在进也是可以的啊,现在只是程序没退出时不能同时登录,程序退出后就不起什么作用了。
>>然后在进也是可以的啊,
>>现在只是程序没退出时不能同时登录,
>>程序退出后就不起什么作用了>>现在的问题是在两台机器上分别登录可同时登上去。
>>在一台机器上登录两次不可以。你要得不就是这种情况吗?
如果要求在服务器中,不管在那一台机器,一个用户只能登录一次的话,
把HOST_NAME字段去掉就可以了如果你要求用户非法退出以后不能重新进入的话,就必须使用其他办法了,
我的办法是确保非法退出以后仍能进入
代码如下:
procedure TForm1.Button1Click(Sender: TObject);
begin
ADOConnection1.BeginTrans ;
try
ADOCommand1.CommandText :='INSERT INTO USER1 VALUES (11)'; ’这里只写入用户 名为11
ADOCommand1.Execute ;
except
'提示出错代码(不知道为什么,出错时不执行这里的代码)
end;
end;procedure TForm1.Button2Click(Sender: TObject);
begin
ADOConnection1.RollbackTrans;
close;
end;在次谢谢了
我没有SQL Server,测试不了为什么不行,因为你在本地不能同时插入同一记录,
那么对于其他机器来说,数据库也是一样处理的
不明白为什么不行
在有
tryexceptend
语句在出错时为什么Except语句下的代码不执行呢?
如果是的话,我的这种办法就不OK了没有深入了解过sql server,不知道它具体的锁定策略是怎样的
我试过了,用别一台机器用别的用户名登录没问题。用同一用户名登录出现程序未响应情况,但关掉前一台机器的程序后,后一台机器的程序就又响应了。不知道怎么解决这个问题啊,苦啊!急盼另请看看是不是代码哪里写的不对啊!!!var
Form1: TForm1;
pan :string;
implementation{$R *.dfm}procedure TForm1.Button1Click(Sender: TObject);begin
tryADOCommand1.CommandText :='INSERT INTO USER1 VALUES (''' + pan + ''')';
ADOCommand1.Execute ;
except
application.MessageBox('ok',pchar('ok'));
end;
end;procedure TForm1.Button2Click(Sender: TObject);
begin
ADOConnection1.RollbackTrans ;
close;
end;procedure TForm1.FormCreate(Sender: TObject);begin
pan:='pan';
ADOConnection1.BeginTrans ;
end;
如果事务在执行插入时持有的是数据页锁或者索引页锁而不是行级锁那就不OK了,
这是要说明的,比较可靠的是用伴水的办法,
要不嫌开销大就自己做一个控制服务程序,,,从你的情况上看来,估计是因为插入相同的记录导致了等待,
而不是因为页的锁定而发生等待,
那么你可以设定超时,SQL Server好像有个set 什么timeout的SQL命令,
你查看一下ADO或者TSQL的文档,应该有的
我以前的程序中也和你有同样的想法,但是后来的实践中发现太失败了,因为系统的异常情况
太复杂,sql server中的事务锁也不能十分准确。导致用户非正常关机后程序经常不能用了。
能的客户怨声载道,我劝你还是把精力用在让程序更加健壮上面去,一个用户的密码是关键,如果他把密码泄漏了,问题在他们,如果他是自己重复登陆,那有什么办法,他要想自己破坏你的系统了,水都没办法。你要把微软的<windows>目录下的东西给删除了,系统不也瘫痪了吗?软件的使用也要规范的。我们程序员无法阻止所有的非法操作。