2013-04-13 2 views
0

멀티 플레이어 뱀 게임을 개발 중입니다. 게임은 자주 (예외는 아니지만) 예외적으로 java.io.StreamCorrupted 예외 유형 코드를 임의로 throw합니다. AC 동일한 전체 StackTrace가 아래에 나와 있습니다.소켓을 통한 java.io.StreamCorruptedException

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

사실 난 돈 문제가있는 곳을 알기 때문에 필요한 것보다 더 많은 코드를 버려 두었을 것입니다.

+0

그것을받을 귀하의'otherRunMethod() 'while'-loop 일 때, 모든 반복에 대해 새로운'OutputStream'을 만들고, 재 작성되지 않은'InputStream'에 쓰려고합니다. 위에 링크 된 질문을 참조하십시오. –

+0

감사합니다. Lukas. 조금 더 자세히 설명해 주시겠습니까? 비슷한 종류의 오류를 찾고있었습니다. – Sohaib

+0

우선, 'InputStream' 생성을 루프 밖으로 이동시키고 루프 내에서만 사용하십시오. –

답변

0

나는 마침내 내 문제에 대한 해결책을 몇 시간 동안 파고 들었다. 나는 복합 문 앞에 선

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

를 작성하는 경우

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. 

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

내가 제거하는 것 : 서버 측 코드에서 은 다음 코드 조각을 참조 StreamCorrupted 예외입니다. 이것이 왜 일어나고 있는지에 대한 제안은 언제든지 환영 할 것입니다. 위에서 설명한대로 나도 같은 예외 문제에 직면

+0

당신은 그 일이 왜 일어 났는지 들었습니다. 소켓 수명 동안 동일한 스트림을 사용해야하며 쓰기 당 새 스트림을 작성하지 않아야합니다. – EJP

+0

그건 작동하지 않습니다. 서버 측에서는 여러 클라이언트에 보낼 필요가있는 단일 출력 스트림이 있기 때문에 실제로는 작동하지 않습니다. 따라서 여러 번 인스턴스화 할 수 있습니다. (내지도 개체를 참조하십시오. 내가 말했듯이 보유하고 있습니다. 그래서 다른 소켓을 다른 출력 스트림이 필요합니다.) 그래서 클라이언트 쪽에서 읽기 당 입력 스트림을 인스턴스화하지 않으면 분명히 StreamCorrupted 예외가 발생합니다 . – Sohaib

+0

위의 내용에서 소켓 당 한 번씩 해당 'ObjectInputStreams'를 인스턴스화해야 함을 암시합니다.연결 당 소켓을 관리 할 수 ​​있다면 한 쌍의 스트림도 관리 할 수 ​​있습니다. – EJP

0

는, (전송) MSG (객체)를 쓰는 동안 , 나는

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

아래로, 새로운 OutputObjectStream를 생성하고이 동일한 교육 위의 결과였다 따라서

가, 새의 OutputStream을 생성하여, MSG를 보내는 경우에 ..... 같은 이미 생성되는 OutputStream 이미 생성되는 InputStream에 의해 수신하여 전송하고, 새의 InputStream viceversa에를 만들어