2009-09-30 62 views
4

我已經使用套接字(無線程)在Java中構建了一個雙人井字遊戲遊戲。我有它的工作,除了在遊戲結束時終止客戶。基本上,我已經設置好了,一旦遊戲結束(服務器識別出勝利或平局),服務器就會向兩個客戶端發送消息。如果客戶端讀取了特定的消息,那麼他們將「脫離」它們的do-while循環並關閉套接字連接。Java插座問題(在井字棋遊戲中)

問題是,無論何時一個客戶端關閉,另一個會「崩潰」 - 它會終止,但不會成功(它會引發錯誤信息)。考慮打開三個終端 - 兩個客戶端和一個服務器。如果我在一個客戶端上點擊「Ctrl-C」(退出),另一個客戶端將停止。客戶應該完全分開,我不明白爲什麼會發生這種情況。

我打算髮布我的服務器代碼和我的客戶端代碼(刪除了Tic Tac Toe邏輯後) - 任何人都可以看到我在做什麼錯了嗎?謝謝!


更新:我添加了打印語句到try-catch,但是這不是停止問題。我收到的錯誤是這樣的:

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

我改變了下面的代碼,包括所有的井字遊戲邏輯。 Requester.java:32是

currentPlayer = (Integer) in.readObject(); 

...在第一個do-try語句後面。任何人都可以看到發生了什麼?

服務器


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(); 
    } 
    } 

}

客戶:


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(); 
    } 

}

...任何幫助都很棒,我一直堅持這一天。謝謝!

+0

什麼是引發的錯誤信息? – 2009-09-30 12:52:50

+0

拋出的錯誤消息是一個ClassCastException - 基本上,如果Client1進行移動,服務器將檢查一個勝利,並且在客戶端執行的結束將檢查「已完成」消息。如果它收到該消息,則Client1將終止,並且Client2將因上述錯誤而崩潰 - 因爲它位於do-while循環的頂部,正在等待來自服務器的第一條指令。 – littleK 2009-09-30 12:57:52

+2

看起來好像你已經成功註釋掉了實際拋出ClassCastException(/ Tic Tac Toe邏輯)的代碼。無法看到您通過網絡發送的內容以及收到的數據的處理方式。 – jarnbjo 2009-09-30 13:05:38

回答

2

當兩個用戶之一關閉程序。連接「中斷」。然後socket類拋出一個IOException,你會發現:

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

但是在捕獲它之後,你什麼都不做。您必須添加一些消息並說連接已中斷。我認爲你的程序不會崩潰,只是停止,因爲他趕上了豁免,並且關閉了finnaly中的流。

希望這會有所幫助。

+0

Martijn- 請看我上面的更新,我收到了一個不同的錯誤... – littleK 2009-09-30 18:43:52

1

在你的服務器類,在你趕上(IOException異常IOException異常){}

你可以捕捉它的ObjectInputStream不得不拋出該異常(因爲關閉客戶端生成的服務器端一個IOException異常),然後發送到另一客戶端「贏,因爲你的對手已斷開連接」

+0

Nettogrof-請參閱上面的我的更新。我試過這樣做,但似乎並沒有什麼錯... – littleK 2009-09-30 18:42:53

1

我認爲你的「syncronization」卡住了。嘗試打印出你讀的變量。並打印你認爲你會閱讀的內容。

例:

// 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); 

執行相同的文字,並比較輸出。 所以你可以看到發送和接收數據同步的問題。

注意:如果您將對象寫入ObjectOutputStream,則會自動刷新。

+0

嗨你能解釋一步一步如何實施使用java套接字的tic tac腳趾 – spt 2012-10-09 12:16:07

1

在這裏的黑暗中刺,但再追一個IOException是不會解決一個ClassCastException,這是你說你收到錯誤的問題:

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

你說行委託的32是:

currentPlayer = (Integer) in.readObject(); 

您試圖將in.readObject()大小寫爲Integer,但它實際上是一個String,因此是例外。

但是,不要只是捕捉異常,鍛鍊爲什麼你得到一個字符串,而不是一個整數。

我的猜測是你發佈的服務器代碼和void sendMessage(int player,String msg)方法。它看起來像你發送一個字符串消息,但期望在另一端的整數。你可能想整理一下