程序运行一切正常,用户从登录到操作到退出都是正常的。
但是在关闭服务器的时候就会出现 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.