最近在写一个联网的小游戏,里面包含了一点聊天的功能.
我现在想要实现的是,每当有玩家加入游戏的时候,这个Client端会发送一个信息,然后Server接收到这个信息后,会将Client发送过来的Id加入到一个列表(使用的TreeSet)里面,并且向所有Client发送这个列表.
奇怪的事出现了...这个列表从Server端发出去的时候,我将它打印出来,是这样的:
send to: anonymous [onymous, anonymous]
send to: onymous [onymous, anonymous]
发送的信息相同,分别发送给了两个客户端,但是我从客户端接受他们并且打印出来..显示的却是不同的信息:
客户端1:
anonymous
[anonymous]
客户端2:
onymous
[onymous, anonymous]其他的文字信息都很正常,都可以收到..为什么这个列表会出现这种情况呢....
求解答..谢了

解决方案 »

  1.   

    Cool,但没法解答。因为这一定不是通讯本身的问题,只能是程序逻辑或控制上的问题。
      

  2.   

    我试过了用同样的类包装一个String对象发送..客户端收到的是一个完整的信息.所以我就排除了通信错误的可能...不过还是想不出来到底哪里有问题,我发送方是这样:c.oos.writeObject(msg);
    c.oos.flush();
    System.out.println("send to: " + c.id + " " + msg);这里我迭代所有socket列表并且发送一个object给客户端.客户端接受:Message msg = (Message) Main.getOis().readObject();
    players = ((ListMsg) msg).getList();//返回一个Set对象
    System.out.println(((ListMsg) msg).getList());这里造成了数据不统一...打了..也打印出来要发送的数据了,是同样的数据:
    send to: anonymous [onymous, anonymous]
    send to: onymous [onymous, anonymous]
      

  3.   


    从你的内容来看,应该是存在对List的意外操作,导致去掉了一个元素。建议把关键代码单独抽出来,List之类的直接写死,进行隔离测试,缩小问题范围。最后但除非有完整代码,否则很难深入探讨了。
      

  4.   

    发送写死的List没有问题...我贴一下关键部分的代码好了
    这里是Client端接受的代码,是一个线程类,专门负责读写过来的Object: Message msg = (Message) Main.getOis().readObject();
    if (msg == null) continue;
    if (msg instanceof ListMsg) {
    players = ((ListMsg) msg).getList();
    System.out.println(Main.getId());
    System.out.println(((ListMsg) msg).getList());
    }这里是Server端接受Socket连接的代码,每连接一个Socket,会为这个socket创建一个单独的线程,用来处理他的读写操作 while (running) {
    Client c = new Client(server.accept());
    new Thread(c).start();
    CLIENTS.add(c);
    }然后是线程里面接受并且发送信息的代码:
    这里是判断如果新加入一个玩家,就把他加入到PLAYERS这个TreeSet中..所有的Client访问的都是同一个PLAYERS对象..这点我非常肯定id = ((TextMsg) msg).getText().substring(TextMsg.PLAYER_JOINED.length());
    newMsg = new TextMsg(TextMsg.SYSTEM_MESSAGE + id + " has joined.");
    PLAYERS.add(new Player(id));
    sendAll(new ListMsg(PLAYERS));
    然后这个sendall方法将向所有的client端发送一个信息(CLIENTS是储存所有Socket的一个集合)
    我就贴关键点的代码了:private void sendAll(Message msg) {
    Iterator<Client> it = CLIENTS.iterator();
    while (it.hasNext()) {
    Client c = null;
    try {
    c = it.next();
    c.getSocket().sendUrgentData(0xFF);
    c.oos.writeObject(msg);
    c.oos.flush();
    System.out.println("send to: " + c.id + " " + msg);
    }...就是这样,谢了
      

  5.   

    我在将集合包装在对象的时候,使用了设置size参数来查看传入集合的长度...
    结果在两边的客户端都显示为2,但是打印集合的时候却只能打印一个...好诡异啊 public ListMsg(Set<Player> players) {
    this.players = players;
    size = players.size();
    }

    public int size() {
    return size;
    }
      

  6.   

    解决了.....发现上面那个问题之后,我就用 public ListMsg(Set<Player> players) {
    this.players = new TreeSet<Player>();
    this.players.addAll(players);
    }这样写构造函数..就可以了,虽然还是不明白为什么,但是解决问题了..
      

  7.   

    你6楼的写法中,只要外部对players有任何删除操作,都会直接影响你的this.players,因为这两者本来就是同一个TreeSet;而由于你size又是固定值,所以当然会一直保持2。而7楼的写法中,你是新建了TreeSet,那然后用addAll重构了TreeSet中所有元素引用;那么外部对players做任何删除,也不会影响你的this.players中的元素个数。所以你看,必然是外部程序逻辑中,删除过players中的元素。