我做了这么一个基于Socket的聊天室:
客户端:建立一个Socket,然后(1)将个人信息以对象的形式发给服务器,(2)接收从服务器生成的ID,(3)再接收从服务器发来的在线用户列表.
接下来进入接收消息循环,当接收到一个消息对象时,显示在GUI上,当接收到一个用户列表时,更新GUI上的用户列表显示....服务器:建立一个ServerSocket,开始监听.每当接到一个请求时,生成一个ID,并用此ID与Socket构造一个客户服务线程.(1)接收客户发来的个人信息(2)向客户端发ID,(3)向所有关客户发更新以后的在线用户列表.感觉如此就可以了.但现在的问题是:
第二个用户上线时,第一个用户会接收到一个更新后的用户列表,但是这个用户列表仍然只有一条数据.第二个用户接收到两条.
而第三个用户上线时,第一个用户仍然接收只有一条数据的列表,第二个用户接收到只有两条数据的列表.第三个用户3条.
第四个用户上线时,第一个用户是:1条,第二个用户:2条,第三个用户:3条.第四个用户:4条.我把服务器端的输出和客户端的接收都打印出来了.
显示是:服务器发了正确的数据,但客户端接收到的不正确.但自己的代码查了下找不出问题.所以来求助高人.因为代码比较长,所以没有贴出来.
有兴趣的可以留个邮箱,我把代码打包发给他.谢谢

解决方案 »

  1.   

    [email protected]
    我看看
      

  2.   

    可能服务器发送的时候有问题!代码看看
    [email protected]
      

  3.   

    从client发送给server的同时,要保留此线程的信息;然后再去接收时,要依次将所有的客户端信息接收进来才可以(当然,应排除自己的信息)
      

  4.   

    no,我最近不太忙,老在csdn上逛,打发时间。
    谁敢抢版主的饭碗?
      

  5.   

    LZ定义个消息对象?通过序列化和反序列化该消息对象,拿到对应的消息进行解析
    至于出现LZ那样的情况,我觉得应该用个键值对的集合去保存客户端连接上来的套接字,要想往某客户端发消息,只要拿到对应的套接字就行,不会出现这样的情况,我也只是用C#做过聊天软件,相信JAVA差不多的,原理是一样的,LZ也可以联系我的QQ
      

  6.   

     我是定义了一个DataPackage对象,里面有一个int type和Object data.在发数据时,把消息或用户列表等数据放到data里面.
    然后用户列表是用的Vector.上线一个用户时,马上将其加入到vector,然后再调用服务器上的方法sendtoall(而不是每个任务线程中的方法)把这个vector发到每个用户上.
      

  7.   

    目前只是设计的被动方式.
    主要是说服务器里面维护一个Vector,保存着在线用户列表,每上线一个用户后就把这个加到Vector里面,然后再用for循环遍历这个Vector里面的用户,将Vector自身发到每一个用户.客户端主要是用ObjectInputStream()封装了一个Socket.
     用Switch处理接到的类,如果读出来的是消息,就显示出来.如果是一个Vector,就把它当用户列表看待,直接更新本地的在线用户列表就可以了.
    但就是出问题:
    第一个用户上线时,会接到一个列表,只有它自己.
    第二个用户上线时,接到一个列表,有它自己和第一个用户,而第一个用户此时接到的列表只有第一个用户
    第三个用户上线时,接到列表中有它自己,第二个用户和第三个用户,而第二个用户接到的列表中只有第二个用户和第一个用户,第一个用户接到的列表只有第一个用户.
    ....如此下去.
    但是问题在于我在服务器端将发送的消息打印出来了,是对每个用户都发了同一个列表(包含正确的当前在线用户信息).
    而客户端接收到数据后,首先将其打印出来,显示的是如上所说的错误数据.
      

  8.   

    精简版代码如下:(缩减为仅有服务器和客户端)
    //Server.java
    import java.io.IOException;
    import java.io.ObjectInputStream;
    import java.io.ObjectOutputStream;
    import java.net.ServerSocket;
    import java.net.Socket;
    import java.util.Vector;
    public class Server {
    Vector<String> v=new Vector<String>();
    Vector<Task> tasklist=new Vector<Task>();
    ServerSocket  server;
    static int count=0;
    Server()throws Exception{
    server=new ServerSocket(9999);
    }
    public static void main(String[] args)throws Exception {
    Server s=new Server();
    s.listen();
    }

    public void listen()throws Exception{
    while(true){
    Socket tmp=server.accept();
    count++;
    Task tmptask=new Task(tmp);
    addUser(tmptask,"user"+count);
    Thread s=new Thread(tmptask);
    s.start();
    }
    }

    public synchronized void addUser(Task t,String u){
    this.tasklist.add(t);
    this.v.add(u);
    }

    public synchronized void removeUser(Task t,String u){
    this.tasklist.remove(t);
    this.v.remove(u);
    }
    public void sendUserToAll()throws IOException {
    Task tmptask;
    System.out.println("#######begin send to all######");
    for(int i=0;i<tasklist.size();i++){
    tmptask=tasklist.get(i);
    tmptask.oos.writeObject(v);
    System.out.println("send v to the port:"+tmptask.socket.getPort()+" ,the v's data is :");
    for(int j=0;j<v.size();j++){
    String s=v.get(i);
    System.out.println("******"+s);
    }

    }
    System.out.println("#######end  send to all######");
    }

    class Task implements Runnable{
    Task(Socket s)throws Exception{
    this.socket=s;
    ois=new ObjectInputStream(s.getInputStream());
    oos=new ObjectOutputStream(s.getOutputStream());
    }
    public Socket socket;
    public ObjectInputStream ois;
    public ObjectOutputStream oos;
    public void run(){
    try{
    sendUserToAll();
    }catch(IOException e){
    e.printStackTrace();
    }
    }
    }
    }//******************
    //Client.java
    import java.net.Socket;
    import java.util.Vector;
    import java.io.IOException;
    import java.io.ObjectInputStream;
    import java.io.ObjectOutputStream;
    public class Client {
    Socket s;
    ObjectInputStream ois;
    ObjectOutputStream oos;

    Client()throws Exception{
    s=new Socket("127.0.0.1",9999);
    oos=new ObjectOutputStream(s.getOutputStream());
    ois=new ObjectInputStream(s.getInputStream());
           }
    public void work()throws Exception {
    while(true){
    Vector v=(Vector)ois.readObject();
    System.out.println("received a vector ,this is the data:");
    for(int i=0;i<v.size();i++){
    System.out.println("******"+(String)(v.get(i)));
    }
    }
    }
    public  static void main(String[] args)throws Exception{
    Client c=new Client();
    c.work();
    }
    }
    运行结果如下:
    运行Client1: java Client
    received a vector ,this is the data:
    ******user1
    received a vector ,this is the data:
    ******user1再打开一个新的CMD,运行Client2: java Client
    received a vector ,this is the data:
    ******user1
    ******user2
    为什么收到的不是同样的数据
    服务器端输出:
    #######begin send to all######
    send v to the port:2563 ,the v's data is :
    ******user1
    #######end  send to all#############begin send to all######
    send v to the port:2563 ,the v's data is :
    ******user1
    ******user1
    send v to the port:2564 ,the v's data is :
    ******user2
    ******user2
    #######end  send to all######
      

  9.   

    楼主程序逻辑与功能基本没有问题。
    1.笔误一处:
    System.out.println("send v to the port:"+tmptask.socket.getPort()+" ,the v's data is :"); 
    for(int j=0;j <v.size();j++){ 
    String s=v.get(i); 
    System.out.println("******"+s); 应该是:
    String s=v.get(j); 2.第二个用户上线时,接到一个列表,有它自己和第一个用户,而第一个用户此时接到的列表只有第一个用户,以此类推:
    本人以为是
    Vector v=(Vector)ois.readObject(); 
    的问题。
    用这种对象传递包括子元素的Vector很难说会有什么结果。估计是和序列化有关。建议使用更底层的通讯,例如字节流。简单修改样例如下:Server:
    public void sendUserToAll()throws IOException { 
    Task tmptask; 
    System.out.println("#######begin send to all######"); 
    for(int i=0;i <tasklist.size();i++){ 
    tmptask=tasklist.get(i); 
    //tmptask.oos.writeObject(v); 
    System.out.println("send v to the port:"+tmptask.socket.getPort()+" ,the v's data is :"); 
    for(int j=0;j <v.size();j++){ 
    tmptask.oos.writeObject((String)v.get(j));
    String s = v.get(j);
    System.out.println("******"+s); 
    } Client:
    while(true){ 
    String v=(Vector)ois.readObject(); 
    System.out.println("received a vector ,this is the data:" + v); 

      

  10.   

    打错了:
    Client: 
    while(true){ 
    String v=(String)ois.readObject(); 
    System.out.println("received a vector ,this is the data:" + v); 

      

  11.   

    [email protected]  我也帮你调试看看吧!
      

  12.   

    这个网上有人帮我改了一下,可以正确运行了.但不知道究竟是为什么.
    他改的是:在服务器端的发送数据的语句前加一句重构oos: tmptask.oos=new ObjectOutputStream(tmptask.socket);
    然后对应的客户端接收数据前也加一句重构ois:ois=new ObjectInputStream(socket)这样就可以得到正常运行的结果了.但是却不知道是什么原因.