【问题标题】:java.io.StreamCorruptedException over sockets [duplicate]套接字上的 java.io.StreamCorruptedException [重复]
【发布时间】:2013-04-05 21:00:14
【问题描述】:

我正在开发一款多人蛇游戏。游戏似乎运行良好,但它经常(不是每次)随机抛出 java.io.StreamCorrupted Exception 类型代码:AC 下面给出了相同的完整 StackTrace。

java.io.StreamCorruptedException: invalid type code: AC
at java.io.ObjectInputStream.readObject0(Unknown Source)
at java.io.ObjectInputStream.readArray(Unknown Source)
at java.io.ObjectInputStream.readObject0(Unknown Source)
at java.io.ObjectInputStream.defaultReadFields(Unknown Source)
at java.io.ObjectInputStream.readSerialData(Unknown Source)
at java.io.ObjectInputStream.readOrdinaryObject(Unknown Source)
at java.io.ObjectInputStream.readObject0(Unknown Source)
at java.io.ObjectInputStream.readObject(Unknown Source)
at mycode.ConnectionManager.otherRunMethod(ConnectionManager.java:231)
at mycode.ConnectionManager$1.run(ConnectionManager.java:289)
at java.lang.Thread.run(Unknown Source)

产生错误的客户端代码如下:

void otherRunMethod() {
    try {
        while (true) {
            boolean gameup = false;
            objin = new ObjectInputStream(socket.getInputStream());
            Object insnake = objin.readObject();
            if (((Snake) insnake).player.length() >= 9) {
                if (((Snake) insnake).player.substring(0, 8).equals(
                        "Resigned")) {
                    String[] s = ((Snake) insnake).player.split(",");
                    map.remove(s[1]);
                    continue;
                } else if (((Snake)insnake).player.substring(0, 10)
                        .equals("food_eaten")) {
                    String[] s = ((Snake) insnake).player.split(",");
                    Game.foodx = Integer.parseInt(s[1]);
                    Game.foody = Integer.parseInt(s[2]) + 35;
                    objin = new ObjectInputStream(socket.getInputStream());
                    insnake = objin.readObject();
                    if(((Snake)insnake).score>highestscore){
                        highestscore=((Snake)insnake).score;
                        if(highestscore>=100 && highestscore<200)
                            levelUp(2);
                        else if(highestscore>=200){
                            levelUp(4);
                        }
                    }
                    if (s.length == 4) {
                        System.out.println(s[3]);
                        if (s[3].equals("game_up")) {
                            gameup=true;
                        }
                    }
                }
            }
            Snake temp = new Snake((Snake) insnake);
            map.remove(temp.player);
            map.put(temp.player, temp);
            if(temp.gameover){
                allPlayersEliminated();
            }
            findPos();
            game_UpCheck(gameup);
            Thread.sleep(10);
        }
    } catch (java.net.SocketException s) {
        JOptionPane.showMessageDialog(null, "Server Closed", "ERROR",
                JOptionPane.ERROR_MESSAGE);
        System.exit(0);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

对应的服务器端代码如下:

    void relay(Snake move) {
    boolean foodeaten = false;
    Snake snake = move;
    try {
        if (move != null && move.player.length() > 9) {
            if (move.player.equals("food_eaten")) {
                move.player = move.player + ","
                        + (Snakeserver.randomGenerator.nextInt(100) * 6)
                        + ","
                        + (Snakeserver.randomGenerator.nextInt(100) * 6);
                foodeaten = true;
                snake = (Snake) objin.readObject();
                int rows = Snakeserver.score.getModel().getRowCount();
                int row = 1;
                for (int i = 0; i < rows; i++) {
                    if (((Snake) snake).player
                            .equals((String) Snakeserver.score.getModel()
                                    .getValueAt(i, 0))) {
                        row = i;
                        break;
                    }
                }
                if (snake.score >= 300)
                    move.player += "," + "game_up";
                Snakeserver.score.getModel()
                        .setValueAt(snake.score, row, 1);
            } 
        }

        if (move.gameover) {
            int rows = Snakeserver.score.getModel().getRowCount();
            int row = 1;
            for (int i = 0; i < rows; i++) {
                if (snake.player.equals((String) Snakeserver.score
                        .getModel().getValueAt(i, 0))) {
                    row = i;
                    break;
                }
            }
            Object temp = Snakeserver.score.getModel().getValueAt(row,
                    1);
            temp += "  GAME OVER";
            Snakeserver.score.getModel().setValueAt(temp, row, 1);
        }

        for (Snake name : map.keySet()) {
            if (name != null) {
                if (name.player.equals(snake.player)) {
                    name.copyValues(snake);
                }
                objout = new ObjectOutputStream(map.get(name)
                        .getOutputStream());
                objout.writeObject(move);
                objout.flush();
                if (foodeaten) {
                    objout = new ObjectOutputStream(map.get(name)
                            .getOutputStream());
                    objout.writeObject(snake);
                    objout.flush();
                }
            }
        }
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (ClassNotFoundException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

实际上我不知道问题出在哪里,所以我可能已经转储了不必要的代码。

【问题讨论】:

  • 在您的otherRunMethod()s while-循环中,您为每次迭代创建一个新的OutputStream,并写入一个未重新创建的InputStream。请参阅我上面链接的问题。
  • 谢谢卢卡斯。请您详细说明一下。我正在寻找类似的错误。
  • 对于初学者,将 InputStream 创建移出循环,并且仅在循环内使用它。
  • 有多个播放器。我必须为它们中的每一个创建一个单独的 OutputStream。这就是为什么在服务器方法中进行多次初始化的原因。在客户端方法中,如果我将其移出循环,它总是会抛出 StreamCorrupted Exception 而不是我现在得到的偶然错误。

标签: java exception serialization java-io objectinputstream


【解决方案1】:

我也遇到了与上述相同的异常和问题,是, 在写入(发送)消息(对象)时,我正在创建新的 OutputObjectStream,如下所示

//client or server side
while(true)
{
    ObjectOutputStream out = new ObjectOutputStream(s.getOutputStream());
    out.writeObject(some_msg_object);
}

/* but while reading(receiving), I was not creating new inputObjectReader
ie */
//on other side
while(true)
Message msgReceived = (Message)inputObjectReader.readObject();

这导致了完全相同的教育,

因此,如果发送 msg,通过创建新的 OutputStream,通过创建新的 InputStream 接收它,反之亦然,使用相同的已创建的 OutputStream 发送,由已创建的 InputStream 接收.....

【讨论】:

    【解决方案2】:

    经过几个小时的挖掘,我终于找到了解决问题的方法。 在服务器端代码中看到以下代码:

    for (Snake name : map.keySet()) {
            if (name != null) {
                if (name.player.equals(snake.player)) {
                    name.copyValues(snake);
                }
                objout = new ObjectOutputStream(map.get(name)
                        .getOutputStream());
                objout.writeObject(move);
                objout.flush();
    //rest of code goes here. Closing brackets as above.
    

    如果我写这行

     objout = new ObjectOutputStream(map.get(name).getOutputStream());
    

    复合语句之前

    if (name.player.equals(snake.player)) {
                name.copyValues(snake);
    }
    

    我似乎摆脱了 StreamCorrupted Exception。 任何关于为什么会发生这种情况的建议都将受到欢迎。

    【讨论】:

    • 您已被告知为什么会发生这种情况。您应该在套接字的整个生命周期中使用相同的流,而不是每次写入都创建新的流。
    • 那行不通。实际上无法工作,因为在服务器端有一个需要发送到多个客户端的输出流。所以它“必须”被多次实例化。 (请查看我的地图对象。正如我所说,它包含 。所以不同的套接字需要不同的输出流。)因此,如果我没有在客户端每次读取时实例化输入流,它显然会导致 StreamCorrupted Exception。
    • 我上面所说的暗示你必须在每个套接字上实例化相应的ObjectInputStreams 一次。如果您可以为每个连接管理一个套接字,那么您也可以管理一对流。
    • 感谢 EJP 的建议。现在考虑以下情况。我收到来自客户端 1 的消息。总共有 10 个客户端。现在需要将此消息转发给所有 10 个客户端。现在根据您的建议,我只允许实例化我的 OutputStream 一次。那么我如何将它传达给所有 10 个客户。他们确实有不同的地址吗?你们这些人是 Java 和套接字方面的专家,我想我无法更好地解释自己。你的建议似乎是不可能的。如果我只实例化一次我的流,我如何将它转发给我的所有 10 个客户端?
    • 我会再试一次。 每个 Socket 必须实例化一个 ObjectInputStream 和一个 ObjectOutputStream。 它确实有效,但您必须首先实际执行。提示:更改您的 Map 以映射到包含套接字 和 ObjectOutputStream 的对象。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-28
    • 2018-08-03
    • 1970-01-01
    • 2011-11-26
    相关资源
    最近更新 更多