Java - многопользовательский сервер / клиент для игры - PullRequest
0 голосов
/ 18 октября 2010

В настоящее время я пытаюсь реализовать игру Nim с использованием Java, я хочу, чтобы один игрок выступал в качестве сервера, а другой - в качестве игрока.

I 'Я довольно плохо знаком с сетями Java и уже имел опыт использования базового протокола TCP / IP, когда клиент-человек подключается к хосту компьютера.

Проблема, с которой я столкнулся, заключается в том, что мне нужно уметь различать разныеигроки при реализации протокола для игры (протокол является логикой для игры).

В его нынешнем виде я могу позволить одному игроку (клиенту) взаимодействовать с сервером.Все, что происходит, это то, что Клиент может играть в игру, но противодействия нет (Сервер просто отслеживает состояние игры, например, сколько осталось палочек, допустимый ввод и т. Д.).

Как мне добавитьвторой игрок, чтобы занять место хозяина?

Редактировать:

Код клиента и сервера был опубликован, это код, который я использовал, и мне вполне комфортно,Вопрос, который я задаю, будет ли это подходящей основой для реализации многопользовательской игры или мне нужно будет сделать что-то совершенно другое?

Мой протокол Nim: (не проверено)

public class NimLogic 
{
    private static final int WAITING = 0;
    private static final int EVALUATING = 1;
    private static final int ANOTHER = 2;
    private int currentState = WAITING;
    private int theInput = 0;
    private int totalSticks = 10;

    String processInput(String input) {
        String theOutput = null;

        try 
        {
            theInput = Integer.parseInt(input);
        } 
        catch (Exception e) 
        {
            // Ignore conversion error
        }

        switch (currentState) 
        {
        case WAITING:
            theOutput = "Take how many sticks?";
            currentState = EVALUATING;
            break;

        case EVALUATING:

            if(theInput == 1 | theInput == 2 | theInput == 3)
            {
                if (theInput < totalSticks) 
                {
                    totalSticks -= theInput;
                    theOutput = "There are" + totalSticks + " left.";
                } 
                else if (theInput > totalSticks) 
                {
                    theOutput = "Error: You cannot take more sticks than that are available";
                    currentState = EVALUATING;
                } 
            }

            if(totalSticks == 1)
            {
                theOutput = "Game Over! Play again? (Yes = 1, No = 0)...";
                currentState = ANOTHER;
            }
            break;

        case ANOTHER:
            if (theInput == 1) 
            {
                totalSticks = 10;
                currentState = EVALUATING;
                theOutput = "Take how many sticks?";
            } 
            else 
            {
                theOutput = "Bye.";
            }
        }
        return theOutput;
    }
}

Спасибо за помощь!

Редактировать:

Клиент

public class Client
{
   @SuppressWarnings("static-access")
public static void main(String machine[])
   {
      Socket kkSocket = null;
      PrintStream os = null;
      DataInputStream is = null;

      try
      {
         kkSocket = new Socket(machine[0], 4444);
         os = new PrintStream(kkSocket.getOutputStream());
         is = new DataInputStream(kkSocket.getInputStream());
      }
      catch(UnknownHostException e)
      {
         System.err.println("Socket Connect failed on " + machine[0]);
      }
      catch (IOException e)
      {
         System.err.println("Streams failed on " + machine[0]);
      }

      if (kkSocket != null && os != null && is != null )
      {
         try
         {
             String fromServer, fromClient;

             while((fromServer = is.readLine()) != null && !fromServer.equals("Bye."))
             {
                fromClient = JOptionPane.showInputDialog(fromServer);
                os.println(fromClient);
             }
             JOptionPane.showMessageDialog(null, "Goodbye, keep smiling.");
             os.close();
             is.close();
             kkSocket.close();
          }

         catch (UnknownHostException e)
         {
            System.err.println("Can't connect to " + machine[0] + e);
         }
         catch (IOException e)
         {
            e.printStackTrace();
            System.err.println("I/O failed on " +machine[0]);
         }
      }
   }
}

Сервер

public class Server
{
   public static void main(String arg[])
   {
      ServerSocket serverSocket = null;

      try
      {
         serverSocket = new ServerSocket(4444);
      }
      catch (IOException e)
      {
         System.err.println("Can't listen on 4444 -> " + e);
         System.exit(1);
      }

      Socket clientSocket = null;
      try       // allow the client to connect
      {
         clientSocket = serverSocket.accept();
      }
      catch (IOException e)
      {
         System.err.println("Failed accept on 4444 -> " + e);
         System.exit(1);
      }

      try
      {
         DataInputStream is =
            new DataInputStream(new BufferedInputStream
                           (clientSocket.getInputStream()));
         PrintStream os =
            new PrintStream(new BufferedOutputStream
              (clientSocket.getOutputStream(), 1024), false);
         GuessState kks = new GuessState();
         String inputLine, outputLine;

         outputLine = kks.processInput(null);
         os.println(outputLine);
         os.flush();

         while((inputLine = is.readLine()) != null
                && !outputLine.equals("Bye."))
         {
            outputLine = kks.processInput(inputLine);
            os.println(outputLine);
            os.flush();
         }
         os.close();
         is.close();
         clientSocket.close();
         serverSocket.close();
      }
      catch (IOException e)
      {
         e.printStackTrace();
      }
   }
}

Ответы [ 2 ]

1 голос
/ 19 октября 2010

Я не совсем уверен, отвечаю ли я на ваш вопрос здесь, поэтому извиняюсь, если нет. Кроме того, прошло некоторое время с тех пор, как я написал какой-либо сетевой код Java, поэтому здесь может быть несколько складок, которые, надеюсь, могут разобраться другие.

Ниже приведена небольшая информация о тех изменениях, которые я, вероятно, внесу, к лучшему или к худшему ...

  • Переработать сетевой код для приема нескольких соединений. Обычно вы делаете это, передавая сокет, возвращенный ServerSocket.accept, потоку для обработки. Если вы имели дело с большим количеством соединений, вы могли бы сделать это, используя вместо этого NIO, но это, вероятно, слишком далеко, чтобы быстро на данный момент.
  • Отделить состояние игры от кода разговора клиента. Для простоты вставьте код разговора клиента в объект потока. Состояние игры должно находиться в объекте, который используется всеми потоками, обслуживающими сокет.
  • Я бы рекомендовал сделать игру должным образом «предметным объектом», а не разбирать строки и т. Д. В ней должны быть такие операции, как «take (clientID, int)», а не «processInput».
  • Попробуйте использовать шаблон наблюдателя для распределения событий от объекта домена потокам сокетов. Примерами событий могут быть 'turnTaken' или 'gameComplete'.
  • Внедрить понятие «повороты» в игровой объект и заставить сервер транслировать событие потокам сокета, объявляя, чья это очередь.

Надеюсь, это даст вам стартер на десять?

1 голос
/ 18 октября 2010

Сервер / клиентский аспект не должен иметь никакого отношения к общению двух игроков. Вы должны иметь возможность порождать два экземпляра игры Nim: один, который прослушивает входящее соединение через какой-либо порт (сервер), и другой, который подключается к нему (клиент). Как только соединение установлено, вы можете передавать Объекты между двумя экземплярами через ваше соединение, которые представляют игровую информацию. Каждый экземпляр вашей игры Nim отвечает за анализ этих игровых данных и запуск на них логики Nim.

По сути, каждый экземпляр игры может работать как сервер или клиент. Вот код, который я написал для шахмат, который должен быть применим. Прочитайте это. В другом месте я создаю экземпляр Сервера или Клиента и сохраняю его в ссылке типа NetworkIdenitity.

   private abstract class NetworkEntity
        extends Thread {

        ObjectOutputStream outputStream;

        ObjectInputStream inputStream;

        Socket connectionHandle;

        Object messageToSend;

        Object receivedMessage;

        public NetworkEntity(final String name) {

            super(name);

        }

        @Override
        public abstract void run();

        public void getStreams()
                throws IOException {
            this.outputStream = new ObjectOutputStream(this.connectionHandle.getOutputStream());
            this.outputStream.flush();
            this.inputStream = new ObjectInputStream(this.connectionHandle.getInputStream());
        }

        public void closeConnection() {

            try {
                if (this.outputStream != null) {
                    this.outputStream.close();
                }
                if (this.inputStream != null) {
                    this.inputStream.close();
                }
                if (this.connectionHandle != null) {
                    this.connectionHandle.close();
                    chatPanel.writeToDisplay("Connection closed with "
                            + this.connectionHandle.getInetAddress().getHostName());
                }
            }
            catch (final IOException e) {
                JOptionPane.showMessageDialog(thisFrame, "Problems experienced when closing connection",
                        "Notification", JOptionPane.ERROR_MESSAGE);
            }

        }

        public void processIncomingData()
                throws IOException {

            do {
                try {
                    this.receivedMessage = this.inputStream.readObject();
                }
                catch (final ClassNotFoundException e) {
                    JOptionPane.showMessageDialog(thisFrame, "read() error: message from "
                            + this.connectionHandle.getInetAddress().getHostName() + " not received", "Notification",
                            JOptionPane.ERROR_MESSAGE);
                }
                if (this.receivedMessage instanceof Move) {
                    final Move m = (Move) this.receivedMessage;
                    System.out.println(getName() + " got move" + m);
                    requestMove(Table.this.chessBoard, Table.this.currentPlayer, Table.this.currentOpponent, m, false);
                    repaint();
                }
                else if (this.receivedMessage instanceof Board) {
                    final Board b = (Board) this.receivedMessage;
                    System.out.println(getName() + " received this board:");
                    b.printCurrentBoardState();
                    // System.out.println("local copy looked like this: " );
                    // chessBoard.printCurrentBoardState();
                    // chessBoard.setGameBoard(b.getGameBoard());
                    // switchCurrentPlayer();
                    // chessBoard.updateBoardState(currentPlayer,
                    // currentOpponent);
                    repaint();
                }
                else if (this.receivedMessage instanceof String) {
                    chatPanel.writeToDisplay((String) this.receivedMessage);
                }
            } while (/* !message.equals("SERVER>>> TERMINATE") */true);

        }

        public void sendData(final Object obj_to_send) {
            try {
                this.outputStream.writeObject(obj_to_send);
                this.outputStream.flush();
            }
            catch (final IOException e) {

            }
        }

    }

    private final class Client
        extends NetworkEntity {

        private final String hostName;

        private final int serverPort;

        public Client(final String host, final int port) {
            super("CLIENT");
            this.hostName = host;
            this.serverPort = port;
        }

        @Override
        public void run() {
            try {
                connectToServer();
                getStreams();
                processIncomingData();
            }
            catch (final EOFException eof) {
            }
            catch (final IOException ioe) {
            }
            catch (final NullPointerException npe) {
            }
            finally {
                closeConnection();
            }
        }

        private void connectToServer()
                throws IOException {
            try {
                this.connectionHandle = new Socket(InetAddress.getByName(this.hostName), this.serverPort);
                connectionEstablished = true;
                chatPanel.writeToDisplay("Successfully connected to "
                        + this.connectionHandle.getInetAddress().getHostName());
            }
            catch (final IOException e) {
                chatPanel.writeToDisplay("Failed to connect to: " + this.hostName);
            }
        }

    }

    private final class Server
        extends NetworkEntity {

        private ServerSocket server;

        private final int listenPort;

        public Server(final int listen_port) {
            super("SERVER");
            this.listenPort = listen_port;
        }

        @Override
        public void run() {

            try {
                this.server = new ServerSocket(this.listenPort, 1);
                chatPanel.writeToDisplay("Listening on port " + this.listenPort);
                try {
                    waitForConnection();
                    getStreams();
                    processIncomingData();
                }
                catch (final EOFException eof) {
                    // System.out.println(getName() + "exception: " +eof);
                    // eof.printStackTrace();
                }
                catch (final IOException ioe) {
                    // System.out.println(getName() + "exception: " +ioe);
                    // ioe.printStackTrace();
                }
                finally {
                    closeConnection();
                }
            }
            catch (final IOException e) {
                JOptionPane.showMessageDialog(thisFrame, "Network Error: " + e, "Notification",
                        JOptionPane.ERROR_MESSAGE);
            }

        }

        private void waitForConnection()
                throws IOException {

            this.connectionHandle = this.server.accept();
            connectionEstablished = true;
            chatPanel.writeToDisplay("Connection received from:" + this.connectionHandle.getInetAddress().getHostName());

        }

        @Override
        public void closeConnection() {

            super.closeConnection();

            try {
                this.server.close();
            }
            catch (final IOException e) {
                chatPanel.writeToDisplay(getName() + "failed to disconnect from the network");
            }

        }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...