使用Delphi7做的程序,DLL里做了个Form,然后把DLL注入到目标进程内使用。使用SQLConnection连接的mysql服务器,KeepConnection设为True。这样如果mysql的网线掉了或者系统崩了,那么客户端就会假死,很有可能崩溃
所以写了1个检测数据库服务器的在线状态的函数,2个用来切换KeepConnection状态的函数,放在线程内执行,结果客户端经常崩溃
是在添加了这部分后程序经常崩溃,所以问题应该出现在这里吧
客户端也不是马上就崩,有的客户端运行了半个小时就崩溃,有的运行了1天也没事function CheckOnline(destip:string): Integer;
var
hICMPDll, hICMP : THandle;
wsaData : TWSADATA;
ICMPCreateFile : TICMPCreateFile;
IcmpCloseHandle : TIcmpCloseHandle;
IcmpSendEcho : TIcmpSendEcho;
IPOpt : TIPOptionInfo;
IPAddr : DWORD;
pReqData,pRevData: PChar;
pIPE : PIcmpEchoReply;
FSize : DWORD;
MyString : string;
FTimeOut : DWORD;
BufferSize : DWORD;
HostEnt : PHostEnt;
sIP : String;
begin
Result := 0;
hICMPdll := LoadLibrary('icmp.dll');
Try
if hICMPDll <> NULL then
begin
WSAStartup($101,wsaData);
@ICMPCreateFile := GetProcAddress(hICMPdll, 'IcmpCreateFile');
@IcmpCloseHandle := GetProcAddress(hICMPdll, 'IcmpCloseHandle');
@IcmpSendEcho := GetProcAddress(hICMPdll, 'IcmpSendEcho');
hICMP := IcmpCreateFile;
IPAddr:= inet_addr(PChar(destip));
if IPAddr = $FFFFFFFF then
begin
HostEnt := gethostbyname(PChar(destip));
if HostEnt <> nil then
sIP := Format('%d.%d.%d.%d', [Byte(HostEnt^.h_addr^[0]), Byte(HostEnt^.h_addr^[1]),
Byte(HostEnt^.h_addr^[2]), Byte(HostEnt^.h_addr^[3])])
else
sIP := '';
IPAddr:= inet_addr(PChar(sIP));
end; FSize := 40;
BufferSize := SizeOf(TICMPEchoReply) + FSize;
GetMem(pRevData,FSize);
GetMem(pIPE,BufferSize);
FillChar(pIPE^, SizeOf(pIPE^), 0);
pIPE^.Data := pRevData;
MyString := 'Hi, OnLine?';
pReqData := PChar(MyString);
FillChar(IPOpt, Sizeof(IPOpt), 0);
IPOpt.TTL := 64;
FTimeOut := 30;
Result:=IcmpSendEcho(hICMP, IPAddr, pReqData, Length(MyString), @IPOpt, pIPE, BufferSize, FTimeOut);
ReNum:=Result; //ReNum是一个全局变量
//如果有返回,返回值表示收到的回复的个数。如果为0表示没有回复,主机无法到达
FreeMem(pRevData);
FreeMem(pIPE);
IcmpCloseHandle(hicmp);
FreeLibrary(hICMPdll);
WSAcleanup();
end;
except //Try
Result:=0;
ReNum:=0;
end;
end;Function SqlOnlineCheck():integer; //检测与mysql服务器的连接是否正常,是个死循环,伴随程序启动就开始检测
begin
Try
SafeStat:=True; //线程处于启用状态
while True do begin
if CheckOnline('192.168.0.10')=0 then begin //与数据库的连接中断
Inc(SqlNum); //与服务器连接中断时间+1,连续4次中断则取消与Sql的连接,SqlNum也是全局变量
if (SqlNum>4)and(Form1.SQLConnection1.KeepConnection=True) then begin
//与Sql服务器间连接中断
Form1.SQLConnection1.KeepConnection :=False;
Form1.SQLConnection1.Connected:=False; //目标数据库不在,取消连接
Form1.sqldataset1.Close;
SqlNum:=0;
end;
end else begin
Sqlnum:=0;
end;
MyWait(500); //每0.5秒循环一次
end;
//EndThread(0);
SafeStat:=False; //线程结束
except
//EndThread(0);
SafeStat:=False; //线程结束
end;
end;Function SqlOnlineCheckTrue():integer; //通过SqlOnlineCheck所获得的SqlNum断开连接的时间,确定是断开连接还是重新连接
begin
Try
if ReNum=0 then begin //ReNum=Sql在线检测的返回值
if (SqlNum>4)and(Form1.SQLConnection1.KeepConnection=True) then begin
Form1.SQLConnection1.KeepConnection :=False;
Form1.SQLConnection1.Connected:=False; //目标数据库不在,取消连接
Form1.sqldataset1.Close;
SqlNum:=0;
end;
end else begin
if (Form1.SQLConnection1.Connected=False)or(Form1.SQLConnection1.KeepConnection=False) then begin
Form1.SQLConnection1.KeepConnection :=True;
Form1.SQLConnection1.Connected:=True; //MySql没有连接则连接上
end;
end;
except
end;
end;//线程启动部分:
if (SafeStat=False) then Safehthread:=BeginThread(nil,0,@SqlOnLineCheck,nil,0,SafeThreadID); //与sql服务器的连接测试没有启动,则启动,每1秒检查一次
Safe2hthread:=BeginThread(nil,0,@SqlOnLineCheckTrue,nil,0,Safe2ThreadID); //每次与sql服务器的连接前测试,大约10秒一次
所以写了1个检测数据库服务器的在线状态的函数,2个用来切换KeepConnection状态的函数,放在线程内执行,结果客户端经常崩溃
是在添加了这部分后程序经常崩溃,所以问题应该出现在这里吧
客户端也不是马上就崩,有的客户端运行了半个小时就崩溃,有的运行了1天也没事function CheckOnline(destip:string): Integer;
var
hICMPDll, hICMP : THandle;
wsaData : TWSADATA;
ICMPCreateFile : TICMPCreateFile;
IcmpCloseHandle : TIcmpCloseHandle;
IcmpSendEcho : TIcmpSendEcho;
IPOpt : TIPOptionInfo;
IPAddr : DWORD;
pReqData,pRevData: PChar;
pIPE : PIcmpEchoReply;
FSize : DWORD;
MyString : string;
FTimeOut : DWORD;
BufferSize : DWORD;
HostEnt : PHostEnt;
sIP : String;
begin
Result := 0;
hICMPdll := LoadLibrary('icmp.dll');
Try
if hICMPDll <> NULL then
begin
WSAStartup($101,wsaData);
@ICMPCreateFile := GetProcAddress(hICMPdll, 'IcmpCreateFile');
@IcmpCloseHandle := GetProcAddress(hICMPdll, 'IcmpCloseHandle');
@IcmpSendEcho := GetProcAddress(hICMPdll, 'IcmpSendEcho');
hICMP := IcmpCreateFile;
IPAddr:= inet_addr(PChar(destip));
if IPAddr = $FFFFFFFF then
begin
HostEnt := gethostbyname(PChar(destip));
if HostEnt <> nil then
sIP := Format('%d.%d.%d.%d', [Byte(HostEnt^.h_addr^[0]), Byte(HostEnt^.h_addr^[1]),
Byte(HostEnt^.h_addr^[2]), Byte(HostEnt^.h_addr^[3])])
else
sIP := '';
IPAddr:= inet_addr(PChar(sIP));
end; FSize := 40;
BufferSize := SizeOf(TICMPEchoReply) + FSize;
GetMem(pRevData,FSize);
GetMem(pIPE,BufferSize);
FillChar(pIPE^, SizeOf(pIPE^), 0);
pIPE^.Data := pRevData;
MyString := 'Hi, OnLine?';
pReqData := PChar(MyString);
FillChar(IPOpt, Sizeof(IPOpt), 0);
IPOpt.TTL := 64;
FTimeOut := 30;
Result:=IcmpSendEcho(hICMP, IPAddr, pReqData, Length(MyString), @IPOpt, pIPE, BufferSize, FTimeOut);
ReNum:=Result; //ReNum是一个全局变量
//如果有返回,返回值表示收到的回复的个数。如果为0表示没有回复,主机无法到达
FreeMem(pRevData);
FreeMem(pIPE);
IcmpCloseHandle(hicmp);
FreeLibrary(hICMPdll);
WSAcleanup();
end;
except //Try
Result:=0;
ReNum:=0;
end;
end;Function SqlOnlineCheck():integer; //检测与mysql服务器的连接是否正常,是个死循环,伴随程序启动就开始检测
begin
Try
SafeStat:=True; //线程处于启用状态
while True do begin
if CheckOnline('192.168.0.10')=0 then begin //与数据库的连接中断
Inc(SqlNum); //与服务器连接中断时间+1,连续4次中断则取消与Sql的连接,SqlNum也是全局变量
if (SqlNum>4)and(Form1.SQLConnection1.KeepConnection=True) then begin
//与Sql服务器间连接中断
Form1.SQLConnection1.KeepConnection :=False;
Form1.SQLConnection1.Connected:=False; //目标数据库不在,取消连接
Form1.sqldataset1.Close;
SqlNum:=0;
end;
end else begin
Sqlnum:=0;
end;
MyWait(500); //每0.5秒循环一次
end;
//EndThread(0);
SafeStat:=False; //线程结束
except
//EndThread(0);
SafeStat:=False; //线程结束
end;
end;Function SqlOnlineCheckTrue():integer; //通过SqlOnlineCheck所获得的SqlNum断开连接的时间,确定是断开连接还是重新连接
begin
Try
if ReNum=0 then begin //ReNum=Sql在线检测的返回值
if (SqlNum>4)and(Form1.SQLConnection1.KeepConnection=True) then begin
Form1.SQLConnection1.KeepConnection :=False;
Form1.SQLConnection1.Connected:=False; //目标数据库不在,取消连接
Form1.sqldataset1.Close;
SqlNum:=0;
end;
end else begin
if (Form1.SQLConnection1.Connected=False)or(Form1.SQLConnection1.KeepConnection=False) then begin
Form1.SQLConnection1.KeepConnection :=True;
Form1.SQLConnection1.Connected:=True; //MySql没有连接则连接上
end;
end;
except
end;
end;//线程启动部分:
if (SafeStat=False) then Safehthread:=BeginThread(nil,0,@SqlOnLineCheck,nil,0,SafeThreadID); //与sql服务器的连接测试没有启动,则启动,每1秒检查一次
Safe2hthread:=BeginThread(nil,0,@SqlOnLineCheckTrue,nil,0,Safe2ThreadID); //每次与sql服务器的连接前测试,大约10秒一次
之所以用线程来执行也就是为了不让检测过程卡客户端的Form
楼主能不能把这个dll代码和注入代码发一下,我正在学这个?