高分:MIDAS监听程序的实现方法(200分)

  • 主题发起人 主题发起人 zcm1975117
  • 开始时间 开始时间
Z

zcm1975117

Unregistered / Unconfirmed
GUEST, unregistred user!
我最近做了一个三层结构的程序,但是我想在服务器端写一个监听界面:具体内容有::
客户机的用户,IP地址,机器名称,登录时间,退出时间!!
请问怎么实现呢???请指教,最好有参考的程序!!高分!!!!!!
 
在服务器端提供一个函数,客户端启动时运行此函数
 
我将以前写的一个logo函数unit给你吧,可以抓IP,网卡号,用户名,机器名称,呵呵,你想要的
都有,但是登录时间和退出时间是登录,退出自己系统而不是WINDOWS的.以面有用到其他单元
的,所以你得稍微改一下,将那几个去掉即可.以前写的,很烂,有的地方本有更好的方法,可我
懒得改了,若你改进后更好,麻烦贴出来,我好拿回去改掉.
unit uLogo;
interface
uses windows,classes,nb30,winsock,db,dbtables,Sysutils,mCommon;
const DataName = 'DM';
var QryLogin:TQuery;
LoginInTime:TDateTime;
function GetComputerName: string;
function GetCurIP: string;
function GetCurrentUserName : string;
procedure WriteLogin(LoginTimes:integer);
procedure WriteLogout;
Function HexBL(by:Byte):string;
procedure NBGetMac(Strings:TStrings);
implementation
uses DM,MyFunction;
Function GetCurrentUserName : string;
var
User : PChar;
Size : DWord;
begin
Size := 128;
GetMem(User, Size);
GetUserName(User, Size);
Result := Trim(StrPas(User));
FreeMem(User);
end;

function GetCurIP: string;
var
ch : ARRAY[1..32] OF Char;
i : Integer;
WSData: TWSAData;
MyHost: PHostEnt;
begin
IF WSAstartup(2,wsdata)<>0 then
begin
Result:='抓IP地址出錯';
Halt(2);
end;
try
IF getHostName(@ch[1],32)<>0 then
begin
Result:='抓IP地址出錯';
Halt(3);
end;
except
halt(3);
end;
MyHost:=GetHostByName(@ch[1]);
IF MyHost=NIL then
begin
Result:='抓IP地址出錯';
END
else
FOR i:=1 TO 4do
begin
Result:=Result+IntToStr(Ord(MyHost.h_addr^[i-1]));
IF i<4 then
Result:=Result+'.'
else
Result:=Result;
end;
end;

function GetComputerName: string;
var
ch : ARRAY[1..32] OF Char;
WSData: TWSAData;
begin
IF WSAstartup(2,wsdata)<>0 then
begin
Result:='抓IP地址出錯';
Halt(2);
end;
try
IF getHostName(@ch[1],32)<>0 then
begin
Result:='抓IP地址出錯';
Halt(3);
end;
except
halt(3);
end;
Result:= StrPas(@ch[1]);
end;

Function HexBL(by:Byte):string;
begin
Result:=Format('%x',[by]);
if Length(Result)<2 then
Result:='0'+Result;
end;

procedure NBGetMac(Strings:TStrings);
var
NCB:TNCB;
Adapter:TAdapterStatus;
LanaEnum:TLanaEnum;
I,J:integer;
Str:String;
begin
Strings.clear;
ZeroMemory(@NCB,SizeOf(NCB));
NCB.ncb_command:=Chr(NCBENUM);
NetBios(@NCB);
NCB.ncb_buffer:=@LanaEnum;
NCB.ncb_Length:=SizeOf(LanaEnum);
NCB.ncb_command:=Chr(NCBENUM);
NetBios(@NCB);
for i:=0 to Ord(LanaEnum.length)-1do
begin
ZeroMemory(@NCB,SizeOf(NCB));
NCB.ncb_command:=Chr(NCBRESET);
NCB.ncb_Lana_num:=LanaEnum.lana;;
NetBios(@NCB);
ZeroMemory(@NCB,SizeOf(NCB));
NCB.ncb_command:=Chr(NCBASTAT);
NCB.ncb_lana_num:=LanaEnum.lana;
StrPCopy(NCB.ncb_callname,'*');
NCB.ncb_buffer:=@Adapter;
NCB.ncb_length:=SizeOf(Adapter);
NetBios(@NCB);
str:='';
for j:=0 to 5do
begin
if j>0 then
Str:=Str+'-';
Str:=Str+HEXBL(Byte(Adapter.adapter_address[j]));
end;
Strings.add(str);
end;
end;

procedure WriteLogin(LoginTimes:integer);
var SysUserName:String;
IPAddress:string;
LogTime:string;
ComputerName:String;
sSQL:string;
AddressList:TStringList;
begin
AddressList:= TStringlist.Create;
NBGetMac(AddressList);
Address:=AddressList.Strings[0];
SysUserName:=GetCurrentUserName;
IPAddress:=GetCurIP;
ComputerName:=GetComputerName;
LoginInTime:=GetServerTime;
LogTime:=FormatDateTime('yyyy/mm/dd HH:MM:SS',LoginInTime);
sSQL:='insert into loginuser(user_name,sys_name,log_time,ip_address,net_address,log_name,com_name,status) values(';
sSQL:=sSQL+''''+UserName+''',';
sSQL:=sSQL+''''+UpperCase(CurSysID)+''''+',';
sSQL:=sSQL+'to_date('+''''+LogTime+''','+'''yyyy/mm/dd HH24:MI:SS'''+'),';
sSQL:=sSQL+''''+IPAddress+''''+',';
sSQL:=sSQL+''''+Address+''''+',';
sSQL:=sSQL+''''+SysUserName+''''+',';
sSQL:=sSQL+''''+Copy(ComputerName,1,15)+''''+',';
sSQL:=sSQL+''''+IntToStr(LoginTimes)+''''+')';
QryLogin:=TQuery.Create(nil);
QryLogin.DatabaseName:=DataName;
QryLogin.SQL.Add(sSQL);
try
QryLogin.ExecSQL;
finally
QryLogin.SQL.Clear;
QryLogin.Free;
end;
end;

procedure WriteLogout;
var LoginOutTime:TDateTime;
StrLTime,StrETime,UseTime:String;
sSQL:string;
begin

LoginOutTime:=GetServerTime;
StrETime:=FormatDateTime('yyyy/mm/dd hh:nn:ss',LoginOutTime);
StrLTime:=FormatDateTime('yyyy/mm/dd hh:nn:ss',LoginInTime);
UseTime:=FormatDateTime('hh:nn:ss',(LoginOutTime-LoginInTime));
sSQL:='update loginuser set exit_time=';
sSQL:=sSQL+'to_date('+''''+StrETime+''','+'''yyyy/mm/dd HH24:MI:SS'''+'),';
sSQL:=sSQL+'use_time='+''''+UseTime+'''';
sSQL:=sSQL+' where user_name='+''''+UserName+'''';
sSQL:=sSQL+' and log_Time=to_date('+''''+StrLTime+''','+'''yyyy/mm/dd HH24:MI:SS'''+')';
sSQL:=sSQL+' and net_Address='+''''+address+'''';
QryLogin:=TQuery.Create(nil);
QryLogin.DatabaseName:=DataName;
QryLogin.SQL.Add(sSQL);
if DM.PDM.DataBase.InTransaction then
DM.PDM.DataBase.Commit;
DM.PDM.DataBase.StartTransaction;
try
try
QryLogin.ExecSQL;
finally
QryLogin.SQL.Clear;
QryLogin.Free;
end;
except
DM.PDM.DataBase.Rollback;
exit;
end;
DM.PDM.DataBase.Commit;
end;

end.
 
我做过,很容易,因为代码涉及到客户端和服务端两部分,比较长,我就不在这贴出来了。
先介绍下原理,如果你需要代码,请给我email,我发给你。
客户端:
客户机的用户,IP地址,机器名称在客户端读取,IP地址,机器名称可以在
注册表中读到;客户机的用户如果是指的客户机主机名,也可以在客户端的注册表中读到。
如果是登陆用户名则不用我说了吧。登陆时,客户端调用一个服务端登陆过程(在服务端定义的,
你应该知道如何做),将这些参数传入。退出时,调用一个服务端退出过程,参数相同。
服务端:
登录时间在服务端登陆过程中从数据库获取(当然也可以直接读取服务端本机时间,
建议不要采用客户端时间)。然后,加上登陆过程传来的参数就可以在服务端的窗口中显示了。
退出时间也在服务端获取,当然是在退出过程中。同样,加上从客户端传来的参数,
你就可以在服务端显示了。
 
我用的也是forest gun的这种方法,写一个服务器接口方法,在客户端登录时将用户名,口令
ip,都传过去就可以了
中间层调用存储过程来校验用户,并把登录信息插入到log表中,
中间层的用一个查询就可以显示在限用户和历史纪录
退出处理类似
 
我也要:
bronzestar@163.com
 
以下是我从自己的应用中节选的服务端的退出和登陆过程代码,供参考。
个人可以根据自己的具体情况进行修改。客户端调用很简单,我就不写了。
procedure TServer_MainControl.UserLeave(const sUserName, sMachine, sip: WideString);
var
spUserLeave:TADOStoredProc;
i: Integer;
begin
//退出系统,调用存储过程登记日志表
spUserLeave:=TAdoStoredProc.Create(self);
spUserLeave.Connection:=adcMainData;
spUserLeave.ProcedureName:='dbo.SpE_UserLeave;1';
with spUserLeave.Parametersdo
begin
CreateParameter('@UserName',ftstring,pdInput,20,sUserName);
CreateParameter('@Machine',ftString,pdInput,20,sMachine);
CreateParameter('@ip',ftstring,pdInput,20,sip);
end;
spUserLeave.ExecProc;
spUserLeave.Free;
//从监控窗口的Listview中删除该用户,当然也可以改为增加退出时间
for i := 0 to Server_Main.mlstView.Items.Count - 1do
begin
if Server_Main.mlstView.Items.Caption = sUserName then
if Server_Main.mlstView.Items.SubItems.Strings[1] = sMachine then
if Server_Main.mlstView.Items.Item.SubItems.Strings[2] = sip then
Break;
end;
if (i >= 0) and (i < Server_Main.mlstView.Items.Count) then
Server_Main.mlstView.Items.Delete;
//Server_Main.StatusBar1.Panels[5].Text:=IntTostr(Server_Main.mlstView.Items.Count);
end;

//登陆系统
function TSvr_MainControl.UserLogin(out sUserName: WideString;
const sMachine, sPasswd, sUserCode,
sip: WideString;
out sConstraintTable: WideString): WideString;
var
i, LoginCnt: Integer;
// UserGrpNo1: string;
UserName: string;
spUserLogin:TADOStoredProc;
begin
Result := '';
LoginCnt := 0;
/// 验证用户登录
Result := CheckUserLogin(sUserCode, sPassWd, sSystem, sGrantee, UserName);
if StrToInt(Result) < 0 then
Exit;
sUserName := UserName;
//调用存储过程登记日志表
spUserLogin:=TAdoStoredProc.Create(self);
spUserLogin.Connection:=adcMainData;
spUserLogin.ProcedureName:='dbo.SpE_UserLogin;1';
with spUserLogin.Parametersdo
begin
CreateParameter('@UserNo',ftstring,pdInput,10,sUserCode);
CreateParameter('@UserName',ftstring,pdInput,20,sUserName);
CreateParameter('@Machine',ftString,pdInput,20,sMachine);
CreateParameter('@ip',ftstring,pdInput,20,sip);
end;
spUserLogin.ExecProc;
sConstraintTable:= spUserLogin.Parameters.ParamByName('@ConstraintTable').value;
spUserLogin.Free;
/// 更新用户信息显示
for i := 0 to Server_Main.mlstView.Items.Count - 1do
begin
if Server_Main.mlstView.Items.Item.Caption = sUserName then
if Server_Main.mlstView.Items.Item.SubItems.Strings[1] = sMachine then
if Server_Main.mlstView.Items.Item.SubItems.Strings[2] = sSysCaption then
if Server_Main.mlstView.Items.Item.SubItems.Strings[4] = sGrantee then
if LoginCnt < StrToInt(Server_Main.mlstView.Items.Item.SubItems.Strings[5]) then
LoginCnt := StrToInt(Server_Main.mlstView.Items.Item.SubItems.Strings[5]);
end;
With Server_Main.mlstView.Items.Adddo
begin
Caption := sUserName;
SubItems.Append('操作');
SubItems.Append(sMachine);
SubItems.Append(sSysCaption);
SubItems.Append(FormatDateTime('yyyy/mm/dd HH:mm:ss', Now));
SubItems.Append(sGrantee);
SubItems.Append(IntToStr(LoginCnt + 1));
end;
Result := IntToStr(LoginCnt + 1);
end;
 
我想问一下,如果异常退出,怎么办呢???????
另外我还想问一个问题:我想监视应用服务器的性能,大家有什么建议!!!其实我主要的目
的就是这个!!!(退评估我这个服务器到底能为多少客户提供服务!!!)
 
关于异常退出:
如果是客户端异常,如连不上应用服务器,则在客户端处理,这应该不是问题。
主要是应用服务器中的异常,如应用服务器连不上数据库(客户端正常连接应用服务器)。
这种情况,最好根据您自己的具体应用要求处理。我做系统的时候,因为应用服务器只有在
客户端主动调用时才动作,因此应用服务器的异常也可以反馈到客户端。
至于应用服务器性能,我没专门测试过,但在nt上我发现每增加一个客户连接内存就要占用一些,
如果服务器内存不多,可能连结数就不多了。而且最好要留下20%内存空闲,否则很容易死机。
(上述结果是使用dcom连接得到的)
 
delphi本身的范例就有
看midas目录下的login项目
 
http://delphi.mychangshu.com/dispdoc.asp?id=199
it is how to logon, about the rest of thing, you might get those information at
client side, then
submit them when the client logon
 
接受答案了.
 
后退
顶部