to windindance(风舞轻扬)
你的方法也是一种解决方案,但是如果用户的IP是动态分配的就不能用了。
另外,建立一个用户表也会造成系统开销。

解决方案 »

  1.   

    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    //取得客户端信息(网卡MacID、计算机名称、IP地址、登陆账号、真实姓名、线程ID、)
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    procedure TCORBAServer_WeiHai.GetClientInfo(const vNetCardID, vComputer, vClientIP, vUser, vName, vThreadID, vStatus: WideString);
      //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      function ClientOnline: integer;
      var i: integer;
      begin
        Result := -1;
        for i:=1 to Clients.Count do
        if vClientIP=TClient(Clients.Items[i-1]).ClientIP
        then begin
               Result := i-1;
               Break;
             end;
      end;
      //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    var ClientID: integer;
        ClientNew: Boolean;
    begin
      ClientNew := ClientOnline<0;//如果ClientOnline<0则认为该客户端为新增用户
      //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      if ClientNew then
      begin
        Clients.Add(Pointer(TClient.Create));
        ClientID := Clients.Count-1;
      end else ClientID := ClientOnline;
      //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      TClient(Clients.Items[ClientID]).NetCardID := vNetCardID;
      TClient(Clients.Items[ClientID]).Computer  := vComputer;
      TClient(Clients.Items[ClientID]).ClientIP  := vClientIP;
      TClient(Clients.Items[ClientID]).User      := vUser;
      TClient(Clients.Items[ClientID]).Name      := vName;
      TClient(Clients.Items[ClientID]).ThreadID  := vThreadID;
      TClient(Clients.Items[ClientID]).LastTime  := Now;
      TClient(Clients.Items[ClientID]).Status    := vStatus;
      //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      //如果是新增客户端则重画StringGrid表面,否则只刷新StringGrid(LastTime,Status)
      //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      if ClientNew then Form_Server.StringGridRepaint else Form_Server.StringGridRefresh(ClientID+1)
    end;
      

  2.   

    将网卡MacID、计算机名称、IP地址、登陆账号、真实姓名、线程ID保存在数组或列表中,新用户登陆时判断该用户在数组或列表是否存在
      

  3.   

    多谢quark(夸克)
    大恩大德,来日再抱~~!
      

  4.   

    这个的确是一个很重要的问题,不然如果用户的电脑出现电源或网络故障,他的用户名就永远挂在系统上,也就不能在登陆了。
    不知道能不能用delphi实现类似于ASP的超时机制
      

  5.   

    那么blackfiles(从来是我伤心) 的公司是用什么办法解决或补救这个问题的呢?
      

  6.   

    我是这样做的
    用户是否上线(true/false)
    如果该用户非法退出。而为把改用户退出的信息返回服务器。可以如下解决
    你一定有一个管理级用户
    用该用户可以察看那些用户在线上,如果非法退出而不可以连接服务器的可以有管理员进行设置更改她的上线为false
    还可以在服务器定时对客户端进行监测看他是否在线如果三次检查都没在线就可见自动将她的上线为false;
      

  7.   

    to:YANGYUGW(yangyu)
    你的方法有一定的道理
    但是,第一种方法需要人工干预,如果系统的规模比较大就很难实现了
    第二种方法的检测间隔很难掌握,容易造成在线用户被踢下线,而且当在线用户比较多的时候系统开销较大
      

  8.   

    可以参考一下qq的做法呀,不过我不太了解qq
    不过一定是服务器进行了检查
      

  9.   

    QQ采用的可能是一种超时机制
    就是如果客户一段时间内没有向服务器发送信息就设置为离线
    但是不知道在delphi中有没有相关的函数可以调用
      

  10.   

    对不起了,这个我也不太知道,不过可以去问问李维
    http://forum.vclxx.org
    希望李维给你方法到时别忘了告诉我这个菜鸟
    :)
      

  11.   

    看看这个,会对你有启发
    http://www.csdn.net/expert/topic/560/560755.xml?temp=.4501764
      

  12.   

    真心感谢大家的参与,经过仔细的思考,决定使用 YANGYUGW(yangyu)的方案,用API函数将机器的硬盘序列号取出来,写到用户信息数据库中,登陆的时候检验数据库中的值和客户电脑硬盘序列号的值是否一致,一致则接受登陆请求,不一致拒绝用户登陆。
    这也许可以在技术上保证一个用户名同时只能有一人使用。
    如果大家也同意我的观点,我就分分数了!