Java套接字 - 接收不同对象的客户端

时间:2017-08-23 13:57:18

标签: java sockets stream

所以我想使用套接字在Java中制作纸牌游戏。我有这个" PlayerState"保持所有在大厅或准备好比赛的球员的对象。问题是即使服务器为所有客户端发送相同的对象,所有客户端都收到不正确数据的不同对象...让我解释一下

所以这是SERVER中发送Object的方法:

private void sendToAll(PlayersState playersState){
    resetLists(playersState.getLobbyPlayers(),playersState.getReadyPlayer());
    Iterator it = clientOutputStreams.iterator();

    while (it.hasNext())
        try {
            ObjectOutputStream writer = (ObjectOutputStream) it.next();
            writer.writeObject(playersState);
            writer.flush();
            System.out.println(playersState.getLobbyPlayers());
        } catch (Exception ex) {
        }
}

这是接收Object

的CLIENT中的方法
private void whileChatting() throws IOException {
        sendMessage("&nume"+nume);
        do {
            try {
                Object object = input.readObject();

                if(object instanceof String)
                    showMessage("\n" + (String) object);

                else if(object instanceof PlayersState){
                    System.out.println(((PlayersState) object).getLobbyPlayers());
                    PlayersState actualPlayerState = new PlayersState();
                    actualPlayerState.setReadyPlayer(((PlayersState) object).getReadyPlayer());
                    actualPlayerState.setLobbyPlayers(((PlayersState) object).getLobbyPlayers());
                    resetLists(actualPlayerState.getLobbyPlayers(),actualPlayerState.getReadyPlayer());
                }

            } catch (ClassNotFoundException var2) {
                showMessage("Unknown data received!");
            }
        } while(!message.equals("SERVER - END"));
    }

这是对象(在CLIENT和SERVER中均可用)

package sample;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;


public class PlayersState implements Serializable{
    private static final long serialVersionUID = 7526472295622776147L;
    private List<String> LobbyPlayers;
    private List<String> ReadyPlayer;

    public PlayersState(){
        LobbyPlayers = new ArrayList<>();
        ReadyPlayer = new ArrayList<>();
    }

    public void removeFrom(String name, List<String> list){
        if(list.contains(name))
            list.remove(name);
    }

    public void addTo(String name, List<String> list){
        list.add(name);
    }

    public List<String> getLobbyPlayers() {
        return LobbyPlayers;
    }

    public void setLobbyPlayers(List<String> lobbyPlayers) {
        LobbyPlayers = lobbyPlayers;
    }

    public List<String> getReadyPlayer() {
        return ReadyPlayer;
    }

    public void setReadyPlayer(List<String> readyPlayer) {
        ReadyPlayer = readyPlayer;
    }
}

如果我一个接一个地打开3个客户端,请说出user1 user2和user3来自SERVER的println的输出将是:

[user1, user2, user3]
[user1, user2, user3]
[user1, user2, user3]

这里一切都很正常。但这是客户收到的:

客户端1(user1):

[user1]
[user1]
[user1]

客户端2(user2)

[user1,user2]
[user1,user2]

客户端3(用户3)

[user1,user2,user3]

为什么客户端没有收到所有相同的数据?

1 个答案:

答案 0 :(得分:-1)

PlayersState不是一个可变类,所以你应该在multiple-thread.like同步它:

tresetLists(playersState.getLobbyPlayers(),playersState.getReadyPlayer());
    Iterator it = clientOutputStreams.iterator();

    byte[] sendBytes=null;
    synchronized (playersState) {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bos);
        oos.writeObject(playersState);
        sendBytes = bos.toByteArray();
        oos.close();
    }

    while (it.hasNext())
        try {
            ObjectOutputStream writer = (ObjectOutputStream) it.next();
            writer.write(sendBytes);
            writer.flush();
            System.out.println(playersState.getLobbyPlayers());
        } catch (Exception ex) {
        }

在上面的代码中,为了提高性能并减少锁定的保持时间,我们锁定playersState并将其序列化为sendBytes数组一次。 当然,您应该随时同步playersState,例如在其他线程上调用getLobbyPlayersgetReadyPlayer