views:

365

answers:

5

Hey everyone,

I have built a two-player tic tac toe game in Java, using sockets (no threads). I have it working, except for terminating the clients when the game is over. Basically, I have it set up so that once a game is over (the server recognizes a win or a draw), then the server will send a message to the two clients. If the clients read that particular message, then they will "break out" of their do-while loops and close the socket connections.

The problem is, whenever one client closes, the other will "crash" - it will terminate, but not successfully (it will throw an error message). Think about having three terminals open - two clients and one server. If I hit "Ctrl-C" (exit) on one client terminal, the other client will stop. The clients should be completely separate, I don't understand why this is happening.

I am going to post my server code and my client code (after having removed the Tic Tac Toe logic) - can anyone see what I'm doing wrong? Thanks!


UPDATE: I added print statements to the try-catch, however that is not stopping the problem. The error I am receiving is this:

 Exception in thread "main" java.lang.ClassCastException: java.lang.String
    at Requester.run(Requester.java:32)
    at Requester.main(Requester.java:142)

I changed the code below to include all of the Tic Tac Toe logic. Requester.java:32 is

 currentPlayer = (Integer) in.readObject();

...right after the first do-try statement. Can anyone see what is going on?

The Server


    import java.io.*;
    import java.net.*;

public class Provider {

  TBoard board = new TBoard();

  ServerSocket providerSocket;
  Socket connection1 = null, connection2 = null;
  ObjectOutputStream out, out2;
  ObjectInputStream in, in2;
  String message;
  Boolean done = false;

  int row;
  int col;

   Provider() {
  }

   void run() {
     try {
        providerSocket = new ServerSocket(20092);

        System.out.println("Waiting for connection...");
        connection1 = providerSocket.accept();
        System.out.println("Connection received from Player 1 "
           + connection1.getInetAddress().getHostName());
        connection2 = providerSocket.accept();
        System.out.println("Connection received from Player 2 "
           + connection2.getInetAddress().getHostName());

        out = new ObjectOutputStream(connection1.getOutputStream());
        out2 = new ObjectOutputStream(connection2.getOutputStream());

        in = new ObjectInputStream(connection1.getInputStream());
        in2 = new ObjectInputStream(connection2.getInputStream());

        do {

           if (board.get_player() == 1) {
              out.writeObject(board.get_player());
              out.flush();
              out.writeObject(board.print_board());
              out.flush();
           } 
           else {
              out2.writeObject(board.get_player());
              out2.flush();
              out2.writeObject(board.print_board());
              out2.flush();
           }

           sendMessage(board.get_player(),
              "Please enter a row, press Enter, then enter a column: ");

           if (board.get_player() == 1) {
              int[][] c_array = (int[][]) in.readObject();
              board.set_array(c_array);
           } 
           else {
              int[][] c_array = (int[][]) in2.readObject();
              board.set_array(c_array);
           }

           if (board.get_player() == 1) {
              board.set_player(2);
           } 
           else {
              board.set_player(1);
           }

           if (board.winner() != 0) {


              System.out.print("The winner is...");

              if (board.get_player() == 1) {
                 System.out.println("Player 2!");
              } 
              else {
                 System.out.println("Player 1!");
              }

              out.writeObject("bye");
              out.flush();
              out2.writeObject("bye");
              out2.flush();

              done = true;


           } 
           else {

              if(board.get_player() == 2){
                 out.writeObject("nothing");
                 out.flush();
              }
              else{
                 out2.writeObject("nothing");
                 out2.flush();
              }


           }

        } while (done != true);

     } 
         catch (IOException ioException) {
           ioException.printStackTrace();
        } 
         catch (ClassNotFoundException e) {
        // TODO Auto-generated catch block
           e.printStackTrace();
        } 
     finally {

        try {

           in.close();
           out.close();
           in2.close();
           out2.close();
           providerSocket.close();
        } 
            catch (IOException ioException) {
              ioException.printStackTrace();
           }
     }
  }

   void sendMessage(int player, String msg) {
     try {
        if (player == 1) {
           out.writeObject(msg);
           out.flush();

        } 
        else {
           out2.writeObject(msg);
           out2.flush();
        }
     } 
         catch (IOException ioException) {
           ioException.printStackTrace();
        }
  }

   public static void main(String args[]) {
     Provider server = new Provider();
     while (true) {
        server.run();
     }
  }

}

The Client:


    import java.io.*;
    import java.net.*;
    import java.util.Scanner;

public class Requester {

  TBoard board = new TBoard();

  Socket requestSocket;
  ObjectOutputStream out;
  ObjectInputStream in;
  String message;
  String endmessage = "";
  int row, col, currentPlayer;

  Scanner scan = new Scanner(System.in);

   Requester() {
  }

   void run() {
     try {
        requestSocket = new Socket("server2.xx.xxxx.xxx", 20092);
        System.out.println("Connected to localhost in port 20092");

        out = new ObjectOutputStream(requestSocket.getOutputStream());
        in = new ObjectInputStream(requestSocket.getInputStream());

        do {
           try {

              currentPlayer = (Integer) in.readObject();
              board.set_player(currentPlayer);

              int[][] b_array = (int[][]) in.readObject();
              board.set_array(b_array);

              for (int i = 0; i < 3; i++) {
                 System.out.println("");
                 for (int j = 0; j < 3; j++) {
                    if (b_array[i][j] == 1) {
                       System.out.print(" X");
                    } 
                    else if (b_array[i][j] == 2) {
                       System.out.print(" O");
                    } 
                    else {
                       System.out.print(" -");
                    }
                 }
              }

              System.out.println();

              message = (String) in.readObject();
              System.out.print(message);

              row = scan.nextInt();
              while (row < 0 || row > 2) {
                 System.out
                    .print("Row is invalid, please choose again (0-2): ");
                 row = scan.nextInt();
              }

              col = scan.nextInt();
              while (col < 0 || col > 2) {
                 System.out
                    .print("Column is invalid, please choose again (0-2): ");
                 col = scan.nextInt();
              }

              while (!board.make_move(row, col)) {
                 System.out
                    .print("The move is not valid. Please choose another row (0-2): ");
                 row = scan.nextInt();

                 while (row < 0 || row > 2) {
                    System.out
                       .print("Row is invalid, please choose again (0-2): ");
                    row = scan.nextInt();
                 }

                 System.out.print("Please choose a column (0-2): ");
                 col = scan.nextInt();

                 while (col < 0 || col > 2) {
                    System.out
                       .print("Column is invalid, please choose again (0-2): ");
                    row = scan.nextInt();
                 }
              }

              for (int i = 0; i < 3; i++) {
                 System.out.println("");
                 for (int j = 0; j < 3; j++) {
                    if (b_array[i][j] == 1) {
                       System.out.print(" X");
                    } 
                    else if (b_array[i][j] == 2) {
                       System.out.print(" O");
                    } 
                    else {
                       System.out.print(" -");
                    }
                 }
              }

              System.out.println();

              out.writeObject(board.print_board());
              out.flush();

              endmessage = (String) in.readObject();

           } 
               catch (ClassNotFoundException classNot) {
                 System.err.println("data received in unknown format");
              }
        } while (!endmessage.equals("bye"));
     } 
         catch (UnknownHostException unknownHost) {
           System.err.println("You are trying to connect to an unknown host!");
        } 
         catch (IOException ioException) {
           ioException.printStackTrace();
        } 
     finally {
        try {
           in.close();
           out.close();
           requestSocket.close();
        } 
            catch (IOException ioException) {
              ioException.printStackTrace();
           }
     }
  }

   void sendMessage(int msg) {
     try {
        out.writeObject(msg);
        out.flush();
     } 
         catch (IOException ioException) {
           ioException.printStackTrace();
        }
  }

   public static void main(String args[]) {
     Requester client = new Requester();
     client.run();
  }

}

...Any help would be great, I've been stuck on this one for days. Thanks!

+1  A: 

In your Server class, in your catch (IOException ioException) { }

you can catch which ObjectInputStream had throws the exception ( because the closing client generate a IOException on the server-side) then send to the another client a "win because you opponent had disconnected"

Nettogrof
Nettogrof- Please see my update above. I tried doing this, but it doesn't seem to be what is wrong...
behrk2
+2  A: 

When one of the two users closes the program. The connection "breaks". Then the socket-class throws an IOException, witch you catch:

   ...
   } catch (IOException ioException) {
            ioException.printStackTrace();
   } 
   ...

But after catching it, you do nothing. You have to add some messages and say that the the connection is broken. I think that your program doesn't crash, just stops because he catch the exeption and than close the streams in the finnaly.

Hope this helps.

Martijn Courteaux
Martijn-Please see my update above, I am receiving a different error...
behrk2
+1  A: 

I think your "syncronization" is stuck. Try to print out the variables you read. And print also what you think you will read.

Exemple:

// Set Current Player
System.out.println("Reading current player");
Object inputCP = in.readObject();
System.out.println(inputCP.getClass().getName() + " " + inputCP);
board.set_player((int) (Integer) inputCP);

Do the same for writing, and compare the outputs. So you can see what is wrong with the syncronization of sending and receiving data.

Note: If you write an object to the ObjectOutputStream he flushes automaticly.

Martijn Courteaux
+1  A: 

A stab in the dark here, but catching an IOException isn't going to solve the problem of a classCastException, which is the error you say your getting:

Exception in thread "main" java.lang.ClassCastException: java.lang.String
at Requester.run(Requester.java:32)
at Requester.main(Requester.java:142)

And you say line 32 of Requester is:

currentPlayer = (Integer) in.readObject();

You are trying to case in.readObject() to an Integer but its actually a String, hence the exception.

But don't just catch the exception, workout why your getting a string instead of an integer.

My guess would be the server code you've posted and the void sendMessage(int player, String msg) method. It looks like your sending a String message but expecting an integer on the other end. you may want to tidy this up a little bit

Richard
A: 

does anyone has a working example of this code? if yes, please send to [email protected] I need it very much. Thanks