我用idtcpserver做服务器作了一个GPRS客户端连接的服务器,请问怎么在客户端连接的情况下关闭服务器?
我的disconnect事件的代码是
procedure TUDP_Client.IdTCPServerDisconnect(AThread: TIdPeerThread);
var
  Client : TClient;
begin
{ Retrieve Client Record from Data pointer }
  Client := Pointer(AThread.Data);
{ Remove Client from the Clients TList }
  Clients.Delete(Client.ListLink);
{ Remove Client from the Clients List Box }
  if  ((Client.Addr<>0) and  (Client.Addr<>1))  then
    lbClients.Items.Delete(lbClients.Items.IndexOf(IntToStr(Client.Addr)))
  else
    lbClients.Items.Delete(lbClients.Items.IndexOf(Client.DNS));
{ Free the Client object }
  Client.Free;
  AThread.Data := nil;
end;
然后做了一个断开连接的按钮:
我做了一个断开连接的按钮
我的代码如下:
procedure TfrmMain.sbtnKillRTUClick(Sender: TObject);
var
  Client : TClient;
begin
  if (lbClients.ItemIndex <> -1) then
    begin
      Client := Clients.Items[lbClients.ItemIndex];
      TIdPeerThread(Client.Thread).Connection.CheckForGracefulDisconnect;
      TIdPeerThread(Client.Thread).Connection.Disconnect;
      lbClients.Items.Delete(lbClients.ItemIndex);
      Clients.Delete(lbClients.ItemIndex);    end;
end;
可是每次按这个断开按钮时总会跳出错误∶raise exception class EIdclosedsocket with message 'Disconnected'
或者list index out of bounds(-1)
或者告诉我not connected
请问这是怎么回事呢?到底应该怎样断开才不会出错呢?
菜鸟急问,请各位高手不吝赐教,谢谢!!!

解决方案 »

  1.   

    断开按钮里面这样
    if lbclients.items.count > 0 then
    begin
      for i := 0 to lbclients.items.count - 1 do
      begin
        TIdPeerThread(clients[i]).connect.disconn...
        ...
      end;
    end;
      

  2.   

    上面的断开全部,也就是说,不管在有多少客户端连接的情况下,你要强行关闭服务器端程序,需要先调用一下上面的代码
    断开某一个的话稍微麻烦一点,在客户端连接的时候,不光要增加连接线程列表了,而且要将它的某个特定信息放到TIdPeerThread的data属性中去,要删除的时候到线程列表中,通过data属性找到那个连接线程,关闭它就可以了
    比如:(在onexec事件中发现是用户登录)
    MyFriendMsg := TFriendMsg.Create;
              MyFriendMsg.UserName := 
              MyFriendMsg.Ip :=           
              ...
              
              AThread.Data := MyFriendMsg;
    这样的话,由于你线程列表的指针已经指向了该AThread,所以你只要循环一下就找到了
      

  3.   

    谢谢!
    我之前也有在connect事件里把Client的信息比如IP什么的放到AThread.Data里去了。
    但是我在断开按钮时是通过在listbox里选定一个连接的client,然后就得到itemindex,也就是之前写得:
    Client := Clients.Items[lbClients.ItemIndex];
    TIdPeerThread(Client.Thread).Connection.CheckForGracefulDisconnect;
    TIdPeerThread(Client.Thread).Connection.Disconnect;
    lbClients.Items.Delete(lbClients.ItemIndex);
    Clients.Delete(lbClients.ItemIndex);然后通过itemindex到之前保存的连接列表里找到那个线程,然后去关闭它。
    问题是我不知道关闭的过程该怎样的,我上面用的关闭流程一直出错,唉
      

  4.   

    最好不要用ItemIndex属性来控制,因为在网络中随时可能会出现各种情况,而如果你没有处理好任何一点,都有可能使lbClients里面的信息和实际的有差别
    Client := Clients.Items[lbClients.ItemIndex];就像你上面写的AThread.Data里面放了IP什么的,那么就也可以多放个名字啊,你选择一个用户断开后,还是循环找名字,就不会出现你说的情况了另外,ondisconn事件里面你先删界面的,再remove(把delete换掉看看)