程序运行一切正常,用户从登录到操作到退出都是正常的。
但是在关闭服务器的时候就会出现 terminate thread timeout这样的错误我是根据indy9demo里的例子写的,indy9demo里的例子在我的机器上运行也会出现 线程终止超时的错误我在想是不是自己的delphi 理的indy 版本和 indy9不一致才导致的问题服务器端的代码如下。。细节部分都没有问题,请大家帮我看看是不是线程上有纰漏
==============================================================================================================procedure Tformserver.getIpAddress;
begin
with CheckListBox do
begin
clear;
items.Add(IdIPWatch1.LocalIP);
end;
end;
function Tformserver.startserver:boolean;//服务器开启函数
var
i:integer;
Binding : TIdSocketHandle;
sl:TStringlist;
begin
sl:=TStringList.Create;
if not stopserver then //如果服务器停止没有被执行,就不执行开启
begin
errorList.Append('停止服务器失败');
result:=false;
exit;
end;
IdTCPServer.Bindings.Clear;
try
try
begin
if editport.Text<>'' then
begin
for i:=0 to self.CheckListBox.Count-1 do
begin
if checklistbox.Checked[i] then
begin
binding:=idtcpserver.Bindings.Add;
binding.IP:=CheckListBox.Items.Strings[i];
binding.Port:=Strtoint(editport.Text);
sl.Append('服务器绑定到IP:'+binding.IP+',端口:'+editport.Text);
end;
end;
IdTCPServer.Active:=true;//服务器开启
result:=Idtcpserver.Active;//返回true;
ServerRunning:=result;//服务器正在运行中,serverRunning:=true;
listboxlog.Items.AddStrings(sl);
listboxlog.Items.Append('服务器已开启');
if result then
StatusBar1.Panels[0].Text:='服务器运行中'
else
StatusBar1.Panels[0].Text:='服务器没有被启动';
end
else
begin
ListBoxLog.Items.Add('端口值不能为空');
result:=false;
exit;
end;
end;
except on exc:exception do
begin
ListBoxLog.Items.Append('服务器未能启动');
errorlist.Append(exc.Message);
result:=false;
ServerRunning:=result;
end;
end;
finally
FreeAndNil(sl);
end;
end;function TFormServer.stopserver:boolean;//服务器停止函数
begin
IdTCPServer.Active:=false;
IdTcpserver.Bindings.Clear;
result:=not IdTCPServer.Active;
ServerRunning:=false; if result then
begin
StatusBar1.Panels[0].Text:='服务器停止';
end
else
begin
StatusBar1.Panels[0].Text:='服务器运行中';
end;
end;//===============================================================================procedure TFormServer.ButtonStartClick(Sender: TObject);//服务器开启按钮
var
j,k:integer;
begin
j:=0;
for k:=0 to CheckListBox.Count-1 do
begin
if checkListBox.Checked[k] then
inc(j);
end;
if j<1 then
begin
ListBoxLog.Items.Add('至少需要选择一个IP地址作为服务器地址');
exit;
end;
errorlist.Clear;
if not startserver then
begin
listboxlog.Items.Append(' 开启服务器错误');
listboxlog.Items.Append(errorlist.Text);
end;
end;procedure TFormServer.ButtonStopClick(Sender: TObject);//服务器停止按钮
begin
errorlist.Clear;
try
if not ServerRunning then
begin
ListBoxLog.Items.Add('服务器未被开启,关闭服务器指令无效');
exit;
end;
if not stopserver then
ListBoxLog.Items.Add('关闭服务器失败'+#13+errorlist.Text)
else
begin
ListBoxLog.Items.Add('服务器已关闭');
end;
except on e:exception do
begin
listboxlog.Items.Add(e.Message);
end;
end;
end;procedure TFormServer.ButtonExitClick(Sender: TObject);
begin
if ServerRunning then
begin
if stopserver then
close
else
MessageDlg('关闭失败,服务器未停止', mtWarning, [mbOK], 0);
end
else
close;
end;procedure TFormServer.IdTCPServerConnect(AThread: TIdPeerThread);
begin
GetMem(newclient,SizeOf(tclient));
newclient.DNS:=AThread.Connection.LocalName;
newclient.Thread:=AThread;
newclient.whetherlogin:=false;
AThread.Data:=TObject(newclient);
try
tl.LockList.Add(newclient);
finally
tl.UnlockList;
end;
self.ListBoxLog.Items.Add(TimeToStr(Time)+'"'+NewClient.DNS+'"'+'连接上服务器');
end;procedure TFormServer.IdTCPServerDisconnect(AThread: TIdPeerThread);
var
ActClient: PClient;
begin
ActClient := PClient(AThread.Data);
listboxlog.Items.Add (TimeToStr(Time)+ActClient^.DNS+'"'+'断开服务器"');
try
if ActClient^.whetherlogin=True then
begin
ListBoxLog.Items.Add('正在准备删除离线用户数据');
sql:='delete * from online where login_number='+actclient^.loginname;
ADOQuery.SQL.Clear;
ADOQuery.SQL.Add(sql);
ADOQuery.ExecSQL;
ListBoxLog.Items.Add('删除成功');
tl.LockList.Remove(ActClient);
end
else
begin
ListBoxLog.Items.Add('即使没有成功登录也需要删除用户');
tl.LockList.Remove(ActClient);
end;
finally
tl.UnlockList;
FreeMem(ActClient);
AThread.Data := nil;
AThread.Free;
end;end;procedure TFormServer.IdTCPServerExecute(AThread:TIdPeerThread);
var actclient,RecClient:pclient;
nicheng,Sql:String;
i:Integer;
recthread:TIdPeerThread;
begin
if not AThread.Terminated and AThread.Connection.Connected then
begin
ListBoxLog.Items.Add('操作在这里开始..');
actclient:=pclient(AThread.Data);
infoget:=AThread.Connection.ReadLn;
if leftstr(infoget,2)='Y:' then
begin
try
i:=ExtractStrings(['@'],[' '],PChar(rightstr(infoget,Length(infoget)-2)),infosl);
sql:='select * from users where user_Number='+infosl.Strings[0]+' and user_password="'+infosl.Strings[1]+'"';
ADOQuery.SQL.Clear;
ADOQuery.SQL.Add(sql);
ADOQuery.Open;
ListBoxLog.Items.Add(infosl.Strings[2]);
if ADOQuery.RecordCount = 0 then //如果输错了用户名和密码
begin
ListBoxLog.Items.Add('用户名或者密码错误');
infosend:='checkfailed';
AThread.Connection.WriteLn(infosend);
end
else
begin
ListBoxLog.Items.Add('用户名和密码正确');
while not adoquery.Eof do //取得当前登录人员的昵称
begin
nicheng:=adoquery.Fields.Fields[3].Value;
adoquery.Next;
end; sql:='select * from online where login_Number='+infosl.Strings[0];
Adoquery.Close;
ADOQuery.SQL.Clear;
ADOQuery.SQL.Add(sql);
adoquery.Open;
if ADOQuery.RecordCount <> 0 then //如果用户已经处于登录状态、、
begin
ListBoxLog.Items.Add('该用户已经处于登陆状态中');
sql:='delete * from online where login_Number='+infosl.Strings[0];
adoquery.Close; //用户已经在线,再登陆的时候就把原来的号顶掉
ADOQuery.SQL.Clear;
ADOQuery.SQL.Add(sql);
adoquery.ExecSQL;
infosend:='hloggingfailed';
AThread.Connection.Write(infosend);
with tl.LockList do
try
for i:=0 to tl.locklist.Count-1 do
begin
RecClient:=Items[i];
if RecClient.loginName=infosl.Strings[0] then
begin
infosend:='havelogging';
recthread:=recclient.thread;
recthread.Connection.Write(infosend);
end;
end;
finally
tl.UnlockList;
end;
end
else
begin
infosend:='loggingSuccess';
AThread.Connection.WriteLn(infosend);
datetime:=now;
ADOQuery.SQL.Clear;
ADOQuery.SQL.Add('insert into online (Login_Number,user_name,User_IPAddress,User_LoginTime) values(:a,:b,:c,:d)');
ADOQuery.Parameters.ParamByName('a').Value:=Strtoint(infosl.Strings[0]);
ADOQuery.Parameters.ParamByName('b').Value:=nicheng;
ADOQuery.Parameters.ParamByName('c').Value:=infosl.Strings[2];
ADOQuery.Parameters.ParamByName('d').Value:=datetime;
ADOQuery.ExecSQL;
newclient.loginName:=infosl.Strings[0];
newclient.whetherlogin:=True;
sql:='select * from online';
Adoquery.Close;
ADOQuery.SQL.Clear;
ADOQuery.SQL.Add(sql);
adoquery.Open;
while not adoquery.Eof do //取得当前登录人员的昵称
begin
username:=username+adoquery.Fields.Fields[0].Text+'@';
userDiminutive:=userDiminutive+adoquery.Fields.Fields[1].Text+'@';
userIpaddress:=userIpaddress+adoquery.Fields.Fields[2].Text+'@';
adoquery.Next;
end;
username:=LeftStr(UserName,Length(username)-1);
userDiminutive:=Copy(userDiminutive,0,Length(userDiminutive)-1);//LeftStr(userDiminutive,Length(userDiminutive)-1);
userIpaddress:=LeftStr(userIpaddress,Length(userIpaddress)-1);
AThread.Connection.WriteLn('N:'+username);//用户名
AThread.Connection.WriteLn('D:'+userDiminutive); //用户昵称
AThread.Connection.WriteLn('I:'+userIpaddress);//用户IP地址 end;
end;
finally
begin
infosl.Free;
end;
end;
end;
end;
end;
procedure TFormServer.FormCreate(Sender: TObject);//程序开启时自动执行
begin
errorlist:=TStringList.Create;
getIpAddress;
sl:=TStringList.Create;
infosl:=TStringList.create;
tl:=tthreadlist.Create;
username:='';
userDiminutive:='';
useripaddress:='';
end;
procedure TFormServer.FormClose(Sender: TObject; var Action: TCloseAction);
begin
idtcpserver.Active:=false;
sl.Free;
Freeandnil(errorlist);//把错误信息列表清空
tl.Free;
end;
end.
但是在关闭服务器的时候就会出现 terminate thread timeout这样的错误我是根据indy9demo里的例子写的,indy9demo里的例子在我的机器上运行也会出现 线程终止超时的错误我在想是不是自己的delphi 理的indy 版本和 indy9不一致才导致的问题服务器端的代码如下。。细节部分都没有问题,请大家帮我看看是不是线程上有纰漏
==============================================================================================================procedure Tformserver.getIpAddress;
begin
with CheckListBox do
begin
clear;
items.Add(IdIPWatch1.LocalIP);
end;
end;
function Tformserver.startserver:boolean;//服务器开启函数
var
i:integer;
Binding : TIdSocketHandle;
sl:TStringlist;
begin
sl:=TStringList.Create;
if not stopserver then //如果服务器停止没有被执行,就不执行开启
begin
errorList.Append('停止服务器失败');
result:=false;
exit;
end;
IdTCPServer.Bindings.Clear;
try
try
begin
if editport.Text<>'' then
begin
for i:=0 to self.CheckListBox.Count-1 do
begin
if checklistbox.Checked[i] then
begin
binding:=idtcpserver.Bindings.Add;
binding.IP:=CheckListBox.Items.Strings[i];
binding.Port:=Strtoint(editport.Text);
sl.Append('服务器绑定到IP:'+binding.IP+',端口:'+editport.Text);
end;
end;
IdTCPServer.Active:=true;//服务器开启
result:=Idtcpserver.Active;//返回true;
ServerRunning:=result;//服务器正在运行中,serverRunning:=true;
listboxlog.Items.AddStrings(sl);
listboxlog.Items.Append('服务器已开启');
if result then
StatusBar1.Panels[0].Text:='服务器运行中'
else
StatusBar1.Panels[0].Text:='服务器没有被启动';
end
else
begin
ListBoxLog.Items.Add('端口值不能为空');
result:=false;
exit;
end;
end;
except on exc:exception do
begin
ListBoxLog.Items.Append('服务器未能启动');
errorlist.Append(exc.Message);
result:=false;
ServerRunning:=result;
end;
end;
finally
FreeAndNil(sl);
end;
end;function TFormServer.stopserver:boolean;//服务器停止函数
begin
IdTCPServer.Active:=false;
IdTcpserver.Bindings.Clear;
result:=not IdTCPServer.Active;
ServerRunning:=false; if result then
begin
StatusBar1.Panels[0].Text:='服务器停止';
end
else
begin
StatusBar1.Panels[0].Text:='服务器运行中';
end;
end;//===============================================================================procedure TFormServer.ButtonStartClick(Sender: TObject);//服务器开启按钮
var
j,k:integer;
begin
j:=0;
for k:=0 to CheckListBox.Count-1 do
begin
if checkListBox.Checked[k] then
inc(j);
end;
if j<1 then
begin
ListBoxLog.Items.Add('至少需要选择一个IP地址作为服务器地址');
exit;
end;
errorlist.Clear;
if not startserver then
begin
listboxlog.Items.Append(' 开启服务器错误');
listboxlog.Items.Append(errorlist.Text);
end;
end;procedure TFormServer.ButtonStopClick(Sender: TObject);//服务器停止按钮
begin
errorlist.Clear;
try
if not ServerRunning then
begin
ListBoxLog.Items.Add('服务器未被开启,关闭服务器指令无效');
exit;
end;
if not stopserver then
ListBoxLog.Items.Add('关闭服务器失败'+#13+errorlist.Text)
else
begin
ListBoxLog.Items.Add('服务器已关闭');
end;
except on e:exception do
begin
listboxlog.Items.Add(e.Message);
end;
end;
end;procedure TFormServer.ButtonExitClick(Sender: TObject);
begin
if ServerRunning then
begin
if stopserver then
close
else
MessageDlg('关闭失败,服务器未停止', mtWarning, [mbOK], 0);
end
else
close;
end;procedure TFormServer.IdTCPServerConnect(AThread: TIdPeerThread);
begin
GetMem(newclient,SizeOf(tclient));
newclient.DNS:=AThread.Connection.LocalName;
newclient.Thread:=AThread;
newclient.whetherlogin:=false;
AThread.Data:=TObject(newclient);
try
tl.LockList.Add(newclient);
finally
tl.UnlockList;
end;
self.ListBoxLog.Items.Add(TimeToStr(Time)+'"'+NewClient.DNS+'"'+'连接上服务器');
end;procedure TFormServer.IdTCPServerDisconnect(AThread: TIdPeerThread);
var
ActClient: PClient;
begin
ActClient := PClient(AThread.Data);
listboxlog.Items.Add (TimeToStr(Time)+ActClient^.DNS+'"'+'断开服务器"');
try
if ActClient^.whetherlogin=True then
begin
ListBoxLog.Items.Add('正在准备删除离线用户数据');
sql:='delete * from online where login_number='+actclient^.loginname;
ADOQuery.SQL.Clear;
ADOQuery.SQL.Add(sql);
ADOQuery.ExecSQL;
ListBoxLog.Items.Add('删除成功');
tl.LockList.Remove(ActClient);
end
else
begin
ListBoxLog.Items.Add('即使没有成功登录也需要删除用户');
tl.LockList.Remove(ActClient);
end;
finally
tl.UnlockList;
FreeMem(ActClient);
AThread.Data := nil;
AThread.Free;
end;end;procedure TFormServer.IdTCPServerExecute(AThread:TIdPeerThread);
var actclient,RecClient:pclient;
nicheng,Sql:String;
i:Integer;
recthread:TIdPeerThread;
begin
if not AThread.Terminated and AThread.Connection.Connected then
begin
ListBoxLog.Items.Add('操作在这里开始..');
actclient:=pclient(AThread.Data);
infoget:=AThread.Connection.ReadLn;
if leftstr(infoget,2)='Y:' then
begin
try
i:=ExtractStrings(['@'],[' '],PChar(rightstr(infoget,Length(infoget)-2)),infosl);
sql:='select * from users where user_Number='+infosl.Strings[0]+' and user_password="'+infosl.Strings[1]+'"';
ADOQuery.SQL.Clear;
ADOQuery.SQL.Add(sql);
ADOQuery.Open;
ListBoxLog.Items.Add(infosl.Strings[2]);
if ADOQuery.RecordCount = 0 then //如果输错了用户名和密码
begin
ListBoxLog.Items.Add('用户名或者密码错误');
infosend:='checkfailed';
AThread.Connection.WriteLn(infosend);
end
else
begin
ListBoxLog.Items.Add('用户名和密码正确');
while not adoquery.Eof do //取得当前登录人员的昵称
begin
nicheng:=adoquery.Fields.Fields[3].Value;
adoquery.Next;
end; sql:='select * from online where login_Number='+infosl.Strings[0];
Adoquery.Close;
ADOQuery.SQL.Clear;
ADOQuery.SQL.Add(sql);
adoquery.Open;
if ADOQuery.RecordCount <> 0 then //如果用户已经处于登录状态、、
begin
ListBoxLog.Items.Add('该用户已经处于登陆状态中');
sql:='delete * from online where login_Number='+infosl.Strings[0];
adoquery.Close; //用户已经在线,再登陆的时候就把原来的号顶掉
ADOQuery.SQL.Clear;
ADOQuery.SQL.Add(sql);
adoquery.ExecSQL;
infosend:='hloggingfailed';
AThread.Connection.Write(infosend);
with tl.LockList do
try
for i:=0 to tl.locklist.Count-1 do
begin
RecClient:=Items[i];
if RecClient.loginName=infosl.Strings[0] then
begin
infosend:='havelogging';
recthread:=recclient.thread;
recthread.Connection.Write(infosend);
end;
end;
finally
tl.UnlockList;
end;
end
else
begin
infosend:='loggingSuccess';
AThread.Connection.WriteLn(infosend);
datetime:=now;
ADOQuery.SQL.Clear;
ADOQuery.SQL.Add('insert into online (Login_Number,user_name,User_IPAddress,User_LoginTime) values(:a,:b,:c,:d)');
ADOQuery.Parameters.ParamByName('a').Value:=Strtoint(infosl.Strings[0]);
ADOQuery.Parameters.ParamByName('b').Value:=nicheng;
ADOQuery.Parameters.ParamByName('c').Value:=infosl.Strings[2];
ADOQuery.Parameters.ParamByName('d').Value:=datetime;
ADOQuery.ExecSQL;
newclient.loginName:=infosl.Strings[0];
newclient.whetherlogin:=True;
sql:='select * from online';
Adoquery.Close;
ADOQuery.SQL.Clear;
ADOQuery.SQL.Add(sql);
adoquery.Open;
while not adoquery.Eof do //取得当前登录人员的昵称
begin
username:=username+adoquery.Fields.Fields[0].Text+'@';
userDiminutive:=userDiminutive+adoquery.Fields.Fields[1].Text+'@';
userIpaddress:=userIpaddress+adoquery.Fields.Fields[2].Text+'@';
adoquery.Next;
end;
username:=LeftStr(UserName,Length(username)-1);
userDiminutive:=Copy(userDiminutive,0,Length(userDiminutive)-1);//LeftStr(userDiminutive,Length(userDiminutive)-1);
userIpaddress:=LeftStr(userIpaddress,Length(userIpaddress)-1);
AThread.Connection.WriteLn('N:'+username);//用户名
AThread.Connection.WriteLn('D:'+userDiminutive); //用户昵称
AThread.Connection.WriteLn('I:'+userIpaddress);//用户IP地址 end;
end;
finally
begin
infosl.Free;
end;
end;
end;
end;
end;
procedure TFormServer.FormCreate(Sender: TObject);//程序开启时自动执行
begin
errorlist:=TStringList.Create;
getIpAddress;
sl:=TStringList.Create;
infosl:=TStringList.create;
tl:=tthreadlist.Create;
username:='';
userDiminutive:='';
useripaddress:='';
end;
procedure TFormServer.FormClose(Sender: TObject; var Action: TCloseAction);
begin
idtcpserver.Active:=false;
sl.Free;
Freeandnil(errorlist);//把错误信息列表清空
tl.Free;
end;
end.
解决方案 »
- 怎样在Delphi安装目录下拷贝第三方控件文件到另一台机的安装目录下
- 请教一下各位大虾,小生两个弱智问题!!
- 如何设置DBGRID,当拖动滚动条时,数据自动滚动??
- delphi中如何实现多个文件拷贝。
- 如何调用Ctrl+C,例如点一个按钮就相当点了Ctrl+C,并拷贝了数据?
- 如何让这些 speedbutton 能成一组???
- 散分:如何在form上显示一个excel表格
- Pascal中有没有中断循环和中段一次循环的语句?
- 请问,怎样使窗体最小化后隐藏,也就是最小化后的小图表不在出现在下面的状态栏中!谢谢,请给出代码!
- 为什么dll里面不能访问网络呢?
- 监听本机25(MAIL)端口发出所有数据并保存
- delphi使用fastreport,subreport怎么指定创建好的page?
我想的是 demo里的例子理论上是没有问题的。但是在我机器上却出现了这样的问题。
可能是indy版本的问题,但是我还了以后还是没能解决问题。。
我在服务器关闭的时候,遍历了所有的线程,然后断开了所有的连接,但是,还是会出现这样的问题。真是搞不懂为什么会出现这样的问题