【问题标题】:Problem with Java Sockets (in tic tac toe game)Java Sockets 的问题(在井字游戏中)
【发布时间】:2009-09-30 12:48:33
【问题描述】:

我已经用 Java 构建了一个双人井字游戏,使用套接字(无线程)。我有它的工作,除了在游戏结束时终止客户端。基本上,我将其设置为一旦游戏结束(服务器识别出胜利或平局),服务器就会向两个客户端发送消息。如果客户端读取了该特定消息,那么它们将“跳出”它们的 do-while 循环并关闭套接字连接。

问题是,每当一个客户端关闭时,另一个客户端就会“崩溃”——它会终止,但不会成功(它会抛出错误消息)。考虑打开三个终端 - 两个客户端和一个服务器。如果我在一个客户端上按“Ctrl-C”(退出),另一个客户端将停止。客户应该完全分开,我不明白为什么会这样。

我将发布我的服务器代码和我的客户端代码(在删除井字游戏逻辑之后) - 谁能看到我做错了什么?谢谢!


更新:我在 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();
  }

}

...任何帮助都会很棒,我已经坚持了好几天了。谢谢!

【问题讨论】:

  • 抛出的错误信息是什么?
  • 抛出的错误消息是 ClassCastException - 基本上,如果 Client1 移动,服务器将检查是否获胜,并且客户端中的 do-while 结束将检查“完成”信息。如果收到该消息,Client1 将终止,并且 Client2 将因上述错误而崩溃 - 因为它位于 do-while 循环的顶部,等待来自服务器的第一条指令..
  • 看起来你已经成功注释掉了代码,实际上抛出了ClassCastException(//井字游戏逻辑)。无法查看您通过网络发送的内容以及接收到的数据如何处理。
  • jarnbjo - 我添加了我的代码,如果你能看一下,我将不胜感激......
  • 是否可以添加 TBoard 类??

标签: java sockets connection


【解决方案1】:

当两个用户之一关闭程序时。连接“中断”。然后套接字类抛出一个 IOException,你可以捕获:

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

但在抓住它之后,你什么也不做。您必须添加一些消息并说连接已断开。我认为你的程序不会崩溃,只是因为他捕捉到异常而停止,然后关闭 finnaly 中的流。

希望这会有所帮助。

【讨论】:

    【解决方案2】:

    在你的 Server 类中,在你的 catch (IOException ioException) { }

    您可以捕捉到哪个 ObjectInputStream 引发了异常(因为关闭客户端在服务器端生成 IOException),然后向另一个客户端发送“因为对手已断开连接而获胜”

    【讨论】:

    • Nettogrof- 请参阅上面的更新。我试过这样做,但似乎没有什么问题......
    【解决方案3】:

    我认为您的“同步”卡住了。尝试打印出您读取的变量。并打印您认为您会阅读的内容。

    示例:

    // 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,他会自动刷新。

    【讨论】:

    • 嗨,你能一步一步解释如何使用java套接字实现井字游戏
    【解决方案4】:

    这里是在黑暗中刺伤,但捕获 IOException 并不能解决 classCastException 的问题,这就是您所说的错误:

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

    你说 Requester 的第 32 行是:

    currentPlayer = (Integer) in.readObject();
    

    您正在尝试将 in.readObject() 转换为 Integer,但它实际上是 String,因此出现异常。

    但不要只捕获异常,要弄清楚为什么你得到一个字符串而不是一个整数。

    我的猜测是您发布的服务器代码和 void sendMessage(int player, String msg) 方法。看起来您发送了一条字符串消息,但在另一端期待一个整数。你可能想稍微整理一下

    【讨论】:

      猜你喜欢
      • 2017-04-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-06-12
      • 2021-12-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多