procedure TForm2.ListView1SelectItem(Sender: TObject; Item: TListItem;
  Selected: Boolean);
begin
  if (listview1.Items.Count>0) and (listview1.SelCount>0)then
    begin
      sel_who:=listview1.Selected.Index;
      caption:=inttostr(sel_who);
    end;
end;procedure TForm2.startbtnClick(Sender: TObject);
begin
  serversocket1.Active:=true;
  richedit1.Lines.Add(datetostr(date)+''+timetostr(time)+'==>>'+
  'yyd聊天服务器启动!');
  richedit1.Lines.Add(datetostr(date)+''+timetostr(time)+'==>>'+
  'yyd聊天服务器昵称!'+label3.Caption);
end;procedure TForm2.stopbtnClick(Sender: TObject);
begin
  serversocket1.Active:=false;
  richedit1.Lines.Add(datetostr(date)+''+timetostr(time)+'==>>'+
  'yyd聊天服务器关闭!');
end;procedure TForm2.namebtnClick(Sender: TObject);
var
  tmpstr:string;
begin
   tmpstr:=inputbox('昵称输入','请输入用户昵称:','');
   if tmpstr<>''then
    begin
     label3.Caption:=tmpstr;
     richedit1.Lines.add(datetostr(date)+''+timetostr(time)+
     '==>>'+'yyd聊天服务器昵称:'+label3.Caption);
    end;
end;procedure TForm2.aboutbtnClick(Sender: TObject);
begin
  showmessage('关于...');
  //shellabout(handle,'yyd聊天工具',#13+'yyd聊天工具1。0版'+#13
  //+'欢迎使用',0);
end;procedure TForm2.quitbtnClick(Sender: TObject);
begin
  close;
end;procedure TForm2.N10Click(Sender: TObject);
begin
         showmessage('帮助请见主页');
      //shellexecute(handle,nil,'帮助.txt',nil ,
     // nil,sw_normal);
end;procedure TForm2.N12Click(Sender: TObject);
begin
       showmessage('关于...');
     //shellabout(handle,'yyd聊天工具',#13+'yyd聊天工具1。0版'+#13
  //+'欢迎使用!',0);
end;procedure TForm2.N9Click(Sender: TObject);
begin
     showmessage('mailto:[email protected]');
  //shellexecute(handle,nil,'mailto:[email protected]',nil,
  //nil,sw_normal);
end;procedure TForm2.N8Click(Sender: TObject);
begin
    showmessage('http//yyd3.com.cn');
  //shellexecute(handle,nil,'http//yyd3.com.cn',nil,
  //nil,sw_normal);
end;procedure TForm2.N6Click(Sender: TObject);
begin
   serversocket1.Active:=true;
   richedit1.Lines.add(datetostr(date)+''+timetostr(time)+
     '==>>'+'yyd聊天服务器启动:'+label3.Caption);
   richedit1.Lines.add(datetostr(date)+''+timetostr(time)+
     '==>>'+'yyd聊天服务器昵称:'+label3.Caption);
end;procedure TForm2.N5Click(Sender: TObject);
begin
    serversocket1.Active:=false;
   richedit1.Lines.add(datetostr(date)+''+timetostr(time)+
     '==>>'+'yyd聊天服务器关闭:'+label3.Caption);
end;procedure TForm2.N4Click(Sender: TObject);
var
  tmpstr:string;
begin
   tmpstr:=inputbox('昵称输入','请输入用户昵称:','');
   if tmpstr<>''then
   begin
   label3.Caption:=tmpstr;
    richedit1.Lines.add(datetostr(date)+''+timetostr(time)+
     '==>>'+'yyd聊天服务器昵称:'+label3.Caption);
    end;
end;procedure TForm2.N2Click(Sender: TObject);
begin
   close;
end;procedure TForm2.ServerSocket1Accept(Sender: TObject;
  Socket: TCustomWinSocket);
var
  newitem:tlistitem;
  ii,jj:integer;
  user,usercur:string;
begin
  newitem:=listview1.Items.Insert(listview1.Items.Count);
   newitem.Caption:='client:'+inttostr(listview1.Items.Count);
   newitem.SubItems.add(socket.RemoteHost);
   newitem.SubItems.Add(socket.RemoteAddress);
   newitem.SubItems.Add(inttostr(socket.RemotePort));
   listview1.Items.Item[listview1.Items.Count-1].Selected:=true;
   display('连接到主机:'+socket.RemoteAddress+'成功');
   ii:=listview1.Itemindex;
     richedit1.Lines.Add(datetostr(date)+''+timetostr(time)+'==>>'
     +listview1.Items[ii].Caption+'加入进来');
     for jj:=0 to listview1.Items.Count-1 do
     begin
     user:=listview1.Items[ii].Caption+'^'+
     listview1.Items[ii].SubItems[0]+'^'
     +listview1.Items[ii].SubItems[1]+'^'
     +listview1.Items[ii].SubItems[2];
      serversocket1.Socket.Connections[jj].SendText('增加用户#!^'+
      user+'^') ;
      end;
end;procedure TForm2.ServerSocket1ClientDisconnect(Sender: TObject;
  Socket: TCustomWinSocket);
  var
    ii,jj:integer;
    user:string;
  begin
   for ii:=0 to listview1.Items.Count-1 do
     begin
     if listview1.Items.Item[ii].SubItems.Strings[2]=
     inttostr(socket.RemotePort)then
        begin
          for jj:=0 to listview1.Items.Count-1 do
          begin
          user:=listview1.Items[ii].Caption+'^'+
          listview1.Items[ii].SubItems[0]+'^'
           +listview1.Items[ii].SubItems[1]+'^'
           +listview1.Items[ii].SubItems[2];
           serversocket1.Socket.Connections[jj].SendText('删除用户#!^'
           +user+'^') ;
          end;
        richedit1.Lines.add(datetostr(date)+''+timetostr(time)+
     '==>>'+listview1.Items[ii].Caption+'走了');;
          listview1.Items.Item[ii].Delete();
          display(socket.RemoteHost+'走了');
        end;
     end;
          if listview1.Items.Count=0 then
          begin
           display('获取信息......');
           end;end;procedure TForm2.ServerSocket1ClientRead(Sender: TObject;
  Socket: TCustomWinSocket);
var
  tmpstr,user:string;
  ii,jj:integer;
  listitem:tlistitem;
  exist:bool;
begin
  exist:=false;
  tmpstr:=socket.ReceiveText;
  if getstring(tmpstr,'^',1)='昵称@#!'then
    begin
      for jj:=0 to listview1.Items.Count-1 do
        begin
         user:=getstring(tmpstr,'^',2);
         serversocket1.Socket.Connections[jj].SendText('交谈@#!^'+user+'^');
        end;
        richedit1.Lines.Add(getstring(tmpstr,'^',2));
    end;
        if getstring(tmpstr,'^',1)='昵称@#!'then
         begin
           for ii:=0 to listview1.Items.Count-1 do
             begin
                if socket.RemotePort=strtoint(listview1.Items[ii].SubItems[2])
                 then
                   begin
                    exist:=true;
                     if getstring(tmpstr,'^',2)<>listview1.Items[ii].Caption
                     then
                     begin
                     richedit1.Lines.Add(datetostr(date)+''+timetostr(time)+
                      '==>>'+listview1.Items[ii].Caption+'更名为'+
                      getstring(tmpstr,'^',2));
                      listview1.Items[ii].Caption:=getstring(tmpstr,'^',2);
                       for jj:=0 to listview1.Items.Count-1 do
                       begin
                         user:=listview1.Items[ii].Caption+'^'+
                          listview1.Items[ii].SubItems[0]+'^'
                          +listview1.Items[ii].SubItems[1]+'^'
                          +listview1.Items[ii].SubItems[2];
                          serversocket1.Socket.Connections[jj].SendText(
                          '昵称@#!^'+user+'^') ;
                       end;                     end;
                    end;
                   end;          end;
end;end.

解决方案 »

  1.   

    好好的检查你的for循环~~~尤其是你的TForm2.ServerSocket1Accept事件中....你的for语句,中第次循环都做相同的string相加,这个浪费的,考虑改成这样:     user:=listview1.Items[ii].Caption+'^'+ //这个放在for语句外面
         listview1.Items[ii].SubItems[0]+'^'
         +listview1.Items[ii].SubItems[1]+'^'
         +listview1.Items[ii].SubItems[2];
    //for jj:=0 to listview1.Items.Count-1 do //改成下面的count-2
    for jj:=0 to listview1.Items.Count-2 do       begin
          serversocket1.Socket.Connections[jj].SendText('增加用户#!^'+
          user+'^') ;
          end;
      

  2.   

    刚才上课去了,我用yahoo发到你邮箱了
      

  3.   

    在ServerSocket1Accept事件里面设断点看看,应该问题在这里,另一个帖子说了
      

  4.   

    看了你的代码,问题了出在客户端:procedure TForm1.ClientSocket1Connect(Sender: TObject;
      Socket: TCustomWinSocket);
    begin
      statusbar1.Panels.Items[0].Text:='连接成功!';//这一句
    end;你的statusbar1没有添加任何的StatusPanel,也就是说状态栏中没有分栏,因此:procedure TForm1.ClientSocket1Connect(Sender: TObject;
      Socket: TCustomWinSocket);
    begin
      //statusbar1.Panels.Items[0].Text:='连接成功!';//这一句改为下面这一句:
        statusbar1.SimpleText:='连接成功!';
    end;
      

  5.   

    谢谢各位朋友指点,‘list index out of bounds’问题在do2008(事情做好了,才是事情) 帮助下已经解决了,第一份贴中已加了分 [服务器端能给客户端发消息,并能列出客户端登陆情况,及昵称改变情况,而客户端却不能给服务器和别的客户端发消息的问题,还没解决,请各位大侠帮忙!!可以在本贴中帮忙回答,一样给50分]
      

  6.   

    客户端的listview没有列出在线用户的原因,是因为通讯格式不对;1.服务器端的unit1.pas中的事件中
    procedure TForm1.ServerSocket1Accept(Sender: TObject;
      Socket: TCustomWinSocket);
    begin
         
          ...
          serversocket1.Socket.Connections[jj].SendText('增加用户#!^'+
          user+'^') ;
    end;注意通讯头为: 增加用户#!^2.客户端unit2.pas的事件中
    procedure TForm1.ClientSocket1Read(Sender: TObject;
      Socket: TCustomWinSocket);begin
      ...
        if getstring(tmpstr,'^',1)='增加用户@#!'then
      ...
    end;接收的通讯头却是: 增加用户@#!
    增加用户#!^ 与 增加用户@#!  比较当然是不相等的所以客户端改成if getstring(tmpstr,'^',1)='增加用户#!'then即可
      

  7.   

    另外有一点,上面的客户端的TForm1.ServerSocket1Accept事件中,
    多次调用了getstring这个函数,每一个if语句都调用了次,这是没有效率的.应该用个临时变量来代替这样var 
    ...
     commHead:string
    ...
    begin
      ...
      tmpstr:=socket.ReceiveText;
      commHead := getstring(tmpstr,'^',1);  if commHead ='昵称@#!'then
      ...
      if commHead='交谈@#!'then
      ...
      if commHead='增加用户#!'then
      ... 
      if commHead='删除用户@#!'then
      

  8.   

    我下载你的附件后,直接运行你编译好的exe确实是服务器和别的客户端还是看不见客户发的消息;但是我没有修改你的代码,直接在我的D7中编译后,就可以了.
    检查一下,是否你没有重新编译呀;另外测试了一下你的程序,发现情况
    1.服务端运行;
    2.客户1进入聊天室,即可在右近的listview中看到自己的信息;到这时,程序算是正确的;
    3.客户2进入聊天室时,就会通知客户1,然后客户1的listview中会显示客户2进来,//这也是正确的;  同时客户2的listview用户用户列表中,也显示了自己的信息;
      但是呢,服务器并没有把客户1的信息,通知给客户2;  客户2的列表中只有自己的信息;  也就是说,后进入聊天室的人,不知道先进入聊室的用户列表;看了一下你的代码,问题出在服务器端的事件:
    procedure TForm1.ServerSocket1Accept(Sender: TObject;
      Socket: TCustomWinSocket);将
         for jj:=0 to listview1.Items.Count-1 do
         begin
           user:=listview1.Items[ii].Caption+'^'+
         listview1.Items[ii].SubItems[0]+'^'
         +listview1.Items[ii].SubItems[1]+'^'
         +listview1.Items[ii].SubItems[2];
          serversocket1.Socket.Connections[jj].SendText('增加用户@#!^'+
          user+'^') ;
          end;这个for循环,改为如下即可  //这个字符串相加,从下面的for循环中独立出来,不必每循环一次就加一次
      user := listview1.Items[ii].Caption + '^' + 
        listview1.Items[ii].SubItems[0] + '^'
        + listview1.Items[ii].SubItems[1] + '^'
        + listview1.Items[ii].SubItems[2];
      
      //通知所有聊天的人,有新的人进来
      for jj := 0 to listview1.Items.Count - 1 do
      begin
        serversocket1.Socket.Connections[jj].SendText('增加用户@#!^' +
          user + '^');
      end;  exit;  //把已经在线的用户列表,通知给刚加入的用户
      for jj := 0 to listview1.Items.Count - 2 do
      begin
        user := listview1.Items[jj].Caption + '^' +
          listview1.Items[jj].SubItems[0] + '^'
          + listview1.Items[jj].SubItems[1] + '^'
          + listview1.Items[jj].SubItems[2];    serversocket1.Socket.Connections[ii].SendText('增加用户@#!^' +
          user + '^');
      end;
      

  9.   

    哦,我说的这个情况,就是你所说的>>,1,能看2,3;2只能看3。。原因是因为服务器没有发送已经在线的用户列表,给刚刚进来的用户而已;如就是说,你原来的一个for语句,是不够的.这个for语句是通知所有已经在线的用户,有新用户进来了.
    需要再加一个for语句,将所以已经在线的用户,通知给刚刚进来的新用户;
    按照上贴中写的两个for循环,替换掉原来的那个for循环即可
      

  10.   

    呵呵,不好意思,有一句调试语句,忘记去掉了
    就是上两楼的exit;这个语句 //这个字符串相加,从下面的for循环中独立出来,不必每循环一次就加一次
      user := listview1.Items[ii].Caption + '^' + 
        listview1.Items[ii].SubItems[0] + '^'
        + listview1.Items[ii].SubItems[1] + '^'
        + listview1.Items[ii].SubItems[2];
      
      //通知所有聊天的人,有新的人进来
      for jj := 0 to listview1.Items.Count - 1 do
      begin
        serversocket1.Socket.Connections[jj].SendText('增加用户@#!^' +
          user + '^');
      end;  //exit; 注释删除这个exit语句,否则下面的这个for循环就不执行了,也就和原来一样,  //把已经在线的用户列表,通知给刚加入的用户
      for jj := 0 to listview1.Items.Count - 2 do
      begin
        user := listview1.Items[jj].Caption + '^' +
          listview1.Items[jj].SubItems[0] + '^'
          + listview1.Items[jj].SubItems[1] + '^'
          + listview1.Items[jj].SubItems[2];    serversocket1.Socket.Connections[ii].SendText('增加用户@#!^' +
          user + '^');
      end;
      

  11.   

    还有你在电子邮件中的>>statusbar1.Panels.Items[0].Text:='连接成功!';就可以用了我试过了,还是出错,因为你的客户端状态条,根本没有分栏statusbar1.SimpleText:='连接成功!'; //这样才不报错
      

  12.   

    真的也,我一直都是修改后光save all让后close all没编译就运行exe,原来真的还要编译才行,晕,现在可以了,还有点小问题想麻烦大侠马上发消息给你还有statusbar1.Panels.Items[0].Text:='连接成功!';在delphi6中不报错,可能和delphi7不一样
      

  13.   

    >>还有点小问题想麻烦大侠就是发现服务器说话,只能最后一个客户端可以看见:如一共客户1,2,3,只能3收到这是你服务器端:
    procedure TForm1.ComboBox1KeyDown(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    begin
     if (key=vk_return)and(combobox1.Text<>'')then
      begin
       combobox1.Items.Add(combobox1.Text);
       serversocket1.Socket.Connections[sel_who].SendText('交谈@#!^'+
       label3.Caption+'说:'+combobox1.Text+'^'); //这里只发送给出一个客户端而已
       //sel_who就是在右边选择一个客户端的数
       richedit1.Lines.Add(label3.Caption+'说:'+combobox1.Text);
       combobox1.Text:='';
      end;
    end;如果服务器说的话,要所有客户端都看得到,这个写一个for循环;上面的代码,改成这样
    procedure TForm1.ComboBox1KeyDown(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    var 
      jj:integer;
      ss:string;
    begin
     if (key=vk_return)and(combobox1.Text<>'')then
      begin
       combobox1.Items.Add(combobox1.Text);
      
       ss := '交谈@#!^'+ label3.Caption+'说:'+combobox1.Text+'^'
       for jj := 0 to listview1.Items.Count - 1 do
       begin
         serversocket1.Socket.Connections[jj].SendText(ss);//给所有客户端发送消息
       end;
       richedit1.Lines.Add(label3.Caption+'说:'+combobox1.Text);
       combobox1.Text:='';
      end;
    end;
      

  14.   

    大侠,我把你的刚改的考上去编译出了点问题:
    1.[Error] Unit1.pas(130): Missing operator or semicolon
    2.[Error] Unit1.pas(133): Incompatible types: 'String' and 'procedure, untyped pointer or untyped parameter'
    3.[Fatal Error] Project1.dpr(5): Could not compile used unit 'Unit1.pas'
    其中1。对应for jj := 0 to listview1.Items.Count-1 do
    2对应本段代码第一个end;
      

  15.   

    终于查清原因了。你写的ss  :=  '交谈@#!^'+  label3.Caption+'说:'+combobox1.Text+'^'
    最后丢了[;],现在已经解决了[服务器说话,只能最后一个客户端可以看见:如一共客户1,2,3,只能3收到  ]但是为什么又出现[多个客户端时只能只能前面先连的看后面的端口等信息,反之不成立,]的问题了,我发给你的最新程序就是这问题[当然‘;’我还没加上去]
      

  16.   

    没有问题吧,,我用你电子邮件中的代码,重新Build就OK了
      

  17.   

    哈哈,这个帖我先结了,让后再去那个帖问最后一个问题[就是怎么让richedit这个字从它的 控件中消失,它默认老在那,多难看呀],就把那个帖也结了,我准备在给这个软件加点功能如踢人,表情,如果有问题,老大你可不能不帮呀,到时我只能开一个50分贴了,[作为新人我只有200分,为了这个程序全献身了,不容易呀。呵呵]