【问题标题】:Server-Client inconsistent results服务器-客户端不一致的结果
【发布时间】:2016-10-11 00:35:48
【问题描述】:

我自己和其他小组成员负责创建游戏的多人游戏方面。为了做到这一点,我们遵循服务器客户端样式。我们能够连接服务器和客户端,我们从服务器向客户端发送 4 条消息。当使用 2 个客户端时,一个客户端会收到 4 个字符串,但第二个客户端会收到一个字符串,该字符串是所有 4 个字符串的组合,中间有白色方块,有时部分消息被截断。

两个客户端产生不同结果的原因可能是什么,一个接收到正确的 4 消息,而另一个接收到的消息是所有 4 的组合?

MainServer 充当游戏的主机,包含服务器套接字和客户端连接。 每个 Client 都连接到一个 Server 类及其与 MainServer 对话的 Server

public class MainServer {

    public GameManager game;
    public Server[] connections; //Array of connected players if server is running.
    public int playerID = 1001;
    public ArrayList<Integer> idList = new ArrayList<Integer>();
    int maxPlayers;
    public MainServer(GameManager game, int maxPlayers){
        this.game = game;   
        this.maxPlayers = maxPlayers;
    }

    public synchronized void runServer(int port){ //As it stands, having the game in server mode will dedicate it to server mode totally.
        try {
            int nclients = 0;
            connections = new Server[maxPlayers];
            //Await connections.
            ServerSocket ss = new ServerSocket(port);
            System.out.println("GAME NOW IN SERVER MODE"+ " Port: "+port+" URL: "+ss.getInetAddress()); 
            while (idList.size() != maxPlayers) { //WHile there are still open players slots
                //Wait for a socket
                //System.out.println("MainServer, before ss.accept()");
                Socket s = ss.accept();
                System.out.println("ACCEPTED CONNECTION FROM: " + s.getInetAddress());  

                connections[nclients] = new Server(s, playerID);
                idList.add(playerID);
                playerID++;
                connections[nclients].start();
                nclients++;
            }

            for (Server s : connections){
                System.out.println(s.playerID);
                if(s.dout==null){System.out.println("dout is null for server "+s.playerID);}
                s.dout.writeUTF("BEGINGAME");
                for (int i : idList){
                    s.dout.writeUTF(Integer.toString(i));
                }
                s.dout.writeUTF("ENDLIST");
            }


        } catch(IOException e) {
            System.err.println("I/O error: " + e.getMessage());
        } 

    }


public class Server extends Thread {
    public final Socket socket;
    public DataInputStream din;
    public DataOutputStream dout;
    public int playerID;

    public Server(Socket sock, int ID) {
        this.socket = sock;
        playerID = ID;
    }

    public void run() {

        try {

            din = new DataInputStream(socket.getInputStream());
            dout = new DataOutputStream(socket.getOutputStream());

            dout.writeInt(playerID);
            dout.flush();

            String frmClient = "", toClient = "";

            while (!frmClient.equals("stop")) {
                frmClient = din.readUTF();

                //System.out.println("client says: " + frmClient);
                //toClient = frmClient + " :Reply From Server";
                toClient = frmClient;

                sendToAll(toClient);
                dout.flush();
            }
            din.close();
            socket.close();

        } catch (IOException e) {
            System.err.println("Server I/O Error: " + e.getMessage());
            e.printStackTrace(System.err);
        }
    }

    public void sendToAll(String msg) throws IOException {
        for (Server s : GameManager.server.connections) {
            if (s != null && s.dout != null) {
                s.dout.writeUTF(msg);

            }
        }
    }
}

public class Client extends Thread {

    public DataOutputStream output;
    public DataInputStream input;

    private GameManager game;

    private String address;
    private int port;
    public int playerID;
    public ArrayList<String> allIds = new ArrayList<String>();
    private Socket s;
    //
    String l="";
    //

    public ArrayList<String> outBuff = new ArrayList<String>();
    public ArrayList<String> inBuff = new ArrayList<String>();

    public Client(String add, int por, GameManager game) {
        address = add;
        port = por;
        this.game = game;
    }

    public void run() {     
        System.out.println("CLIENT");
        try {
            s = new Socket(address,port);
            DataInputStream input = new DataInputStream(s.getInputStream());
            DataOutputStream output = new DataOutputStream(s.getOutputStream());

            String toServ = "";
            String frmServ = "";

            playerID = input.readInt();

            while (!toServ.equals("stop")) {

                toServ = "";
                if(outBuff.size()>0){
                toServ = outBuff.remove(0);}

                if (toServ != null){
                    output.writeUTF(toServ);
                    output.flush();
                }

                frmServ = input.readUTF();


                if(frmServ.length()>0){
                    System.out.println(frmServ+" :test");}              
                if (frmServ != null&&frmServ.length()>0){
                    if (frmServ.equals("BEGINGAME")){
                        //System.out.println("2");
                        while (!frmServ.equals("ENDLIST")){
                            frmServ = input.readUTF();
                            if (!frmServ.equals("BEGINGAME")&&!frmServ.equals("ENDLIST")&&frmServ.length()>0){
                                System.out.println(frmServ+" :Adding to allIds");
                                allIds.add(frmServ);    
                            }                       
                        }

                        game.beginGame(allIds);

                    }
                    if(!frmServ.equals("BEGINGAME")||!frmServ.equals("ENDLIST")){
                        inBuff.add(frmServ);                        
                    }
                }

                for (int i = 0; i < inBuff.size() - 1; i++){
                    game.applyUpdateFromServer(inBuff.remove(i)); //Possible temporary solution, may cause lag because this thread is going into main game and performing tasks
                }


            }

            output.close();
            s.close();

        } catch (IOException e) {
            System.err.println("Client I/O Error: " + e.getMessage());
            e.printStackTrace(System.err);
        }
    }

}

【问题讨论】:

  • 你能不能正确地格式化这个乱七八糟的东西。
  • 并提出一个实际问题。您没有提出问题或指出什么不起作用。

标签: java sockets jakarta-ee networking


【解决方案1】:

TCP 不维护消息边界。有时,您的服务器发送的单个“消息”将被客户端一次接收一个;有时不是。如果多条消息连续快速地发送到客户端,发送系统(我在这里指的是操作系统而不是您的服务器程序)会将它们捆绑到一个 TCP 段中,并将它们作为一个单元传递给另一个系统。即使这没有发生,接收系统最终也可能会聚合多个接收到的消息,并通过单个接收调用将它们传递给客户端。

您必须始终将自己的消息协议边界强加于 TCP 提供的逻辑流之上。这通常意味着(a)在记录之间放置一个“记录分隔符”(换行符、零字节等),或者(b)在每条记录的开头放置一个标头来指示其长度。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-08-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-25
    • 2011-06-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多