简体   繁体   中英

Java Client-Server Programming: Shared Memory Between Clients

I am developing a simple 2D multiplayer game in Java, following the Client-Server model. The functionality in terms of the socket programming is simple:

  • A Client sends the Server their character data (x position, y position, health points, etc.)
  • The Server registers the updated character data in a table which is storing all the different Clients' character data
  • The Server sends back the table to the Client so that they can render the other characters

I am running into a weird issue that I would like help understanding so I can move forward with the project. Here is the code I'm running right now.

import java.io.IOException;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Set;
import java.util.Vector;
import java.util.HashSet;
import java.util.Scanner;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Server
{

    private static Vector<Integer> IDs = new Vector<>();

    public static void main(String[] args) throws Exception
    {
        ExecutorService pool = Executors.newFixedThreadPool(32);

        try (ServerSocket listener = new ServerSocket(40000)) 
        {
            System.out.println("The server is up.");
            while (true)
            {
                pool.execute(new Player(listener.accept()));
            }
        }
    }

    private static class Player implements Runnable
    {
        private Socket socket;
        private Scanner input;
        private PrintWriter output;
        private int ID;

        public Player(Socket socket)
        {
            this.socket = socket;
            this.ID = IDs.size() + 1;
            IDs.add(ID);
        }

        public void run()
        {
            try
            {
                input = new Scanner(socket.getInputStream());
                output = new PrintWriter(socket.getOutputStream(), true);

                while(input.hasNextLine())
                {
                    String result = "";
                    for(int i = 0; i < IDs.size(); i++)
                    {
                        result += (IDs.get(i) + " ");
                    }
                    output.println(result);
                }
            }
            catch(Exception e)
            {
                System.out.println(e);
            }
        }
    }
}
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;

public class Client {
    public static void main(String[] args) throws Exception {
        try (Socket socket = new Socket("127.0.0.1", 40000)) {
            Scanner scanner = new Scanner(System.in);
            Scanner in = new Scanner(socket.getInputStream());
            PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
            while (scanner.hasNextLine()) {
                out.println(scanner.nextLine());
                System.out.println(in.nextLine());
            }
            in.close();
            scanner.close();
        }
    }
}

What I want to happen is: every time a Client sends any message to the Server, the Server responds with a list of IDs (each Client that connects gets a fresh ID).

What is actually happening:

在此处输入图片说明

在此处输入图片说明

在此处输入图片说明

在此处输入图片说明

The second Client that connects is able to see that there is a first Client that is already connected. But the first Client is not able to see that there is a second Client connected.

Thank you for your help.

The server loop

while(input.hasNextLine())
{
    String result = "";
    for(int i = 0; i < IDs.size(); i++)
    {
        result += (IDs.get(i) + " ");
    }
    output.println(result);
}

never calls input.nextLine() , which means that input.hasNextLine() is always true, so the server floods the socket with output until the buffer is full.

This can be seen by starting a client, killing the server, then keep pressing enter. The client keeps receiving data, even though the server is gone, until the buffer is emptied.

Add the following line inside the loop:

System.out.println(this.ID + ": " + input.nextLine());

This will make the server consume the line from the client, as was intended, and allow you to see / verify the data flowing.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM