2012-05-27 39 views
7

Temel olarak bir istemci-sunucu çok oyunculu oyun yazıyor. Bir RequestForGame alırsa bir gameThread oluşturan bir SeverCommunicationThread var bir gameThread oluşturur. Bir RequestForGame istisnası gönderdiğimde java.io.StreamCorruptedException istisnası atılır: geçersiz tür kodu: 00 Her iki iş parçacığının aynı ObjectInputStream okumayı denediğinden dolayı, bunun nasıl çalıştığına dair pek bir fikrim yok, sadece nasıl olduğunu biliyorum onu kullanmak için. Sorunun ne olduğunu ve nasıl düzeltileceğini anlamama yardımcı olabilir misiniz? Teşekkür :)java.io.StreamCorruptedException: geçersiz tür kodu: 00

public class ServerCommunicationThread extends Thread{ 
private Socket connectionSocket; 
private ObjectInputStream inFromClient; 
private ObjectOutputStream outToClient; 
private String nickname; 
private ServerModelManager model; 


public ServerCommunicationThread(Socket connectionSocket, 
     ServerModelManager model) throws IOException { 
    this.connectionSocket = connectionSocket; 
    inFromClient = new ObjectInputStream(connectionSocket.getInputStream()); 
    outToClient = new ObjectOutputStream(connectionSocket.getOutputStream()); 
    this.model = model; 
    start(); 

} 

public void run() { 
    try { 
     String nickname = (String) inFromClient.readObject(); 
     if (model.exists(nickname)){ 
      System.out.println(nickname + " already exists"); 
      outToClient.writeObject(new MessageForClient("Please choose another nickname")); 
     } 
     else 
     { 
      System.out.println(nickname + " connected, adding to list"); 
      model.addClient(nickname, connectionSocket,outToClient,inFromClient); 
      this.nickname=nickname; 
     } 
     while(true){ 
      Object o= inFromClient.readObject();//StreamCorruptedexception 
      if(o instanceof RequestForGame) 
      { 
       RequestForGame r=(RequestForGame)o; 
       String userToPlayWith=r.getUserToPlayWith(); 
       if(userToPlayWith.equals(nickname)) 
       { 
        String message="Playing with yourself makes your palms hairy, choose another opponent"; 
        outToClient.writeObject(message); 
       } 
       else 
       { 
       System.out.println("received request to play with "+userToPlayWith+". starting game"); 
       ClientRepresentative client1=model.getClient(nickname); 
       ClientRepresentative client2=model.getClient(userToPlayWith); 
       ServerGameThread s=new ServerGameThread(client2,client1,client2.getInStream(),client1.getInStream(),client1.getOutStream(),client2.getOutStream()); 
       } 
      } 
      else if(o instanceof String) 
      { 
       String s=(String) o; 
       if(s.equals("i want to quit")) 
       { 
        model.deleteClient(nickname); 
        inFromClient.close(); 
        String q="quit"; 
        outToClient.writeObject(q); 
        connectionSocket.close(); 
        System.out.println(nickname+"has quit without exc"); 
       } 
      } 
     } 
    } catch (EOFException e) { 
     System.out.println(nickname+" has quit"); 
    } 
    catch (SocketException e) 
    { 
     System.out.println(nickname+" has quit"); 
    } 

    catch (Exception e) { 

     e.printStackTrace(); 
    } 
} 

} 
public class ServerGameThread extends Thread { 

private ClientRepresentative client1,client2; 
private ObjectInputStream inFromClient1,inFromClient2; 
private ObjectOutputStream outToClient1,outToClient2; 
private Field gameField; 
public ServerGameThread(ClientRepresentative client1, ClientRepresentative client2,ObjectInputStream inFromClient1,ObjectInputStream inFromClient2,ObjectOutputStream outToClient1,ObjectOutputStream outToClient2) 
{ 
    System.out.println("startin game thred"); 
    this.client1=client1;//client 1 goes first 
    this.client2=client2;//client 2 started game 


     this.inFromClient1=inFromClient1; 
     this.inFromClient2=inFromClient2; 
     this.outToClient1=outToClient1; 
     this.outToClient2=outToClient2; 


     gameField=new Field(); 
     System.out.println("check"); 
     start(); 
} 
public void run() 
{ 
    System.out.println("Starting game. players: "+client1.getNickname()+";"+client2.getNickname()); 
    try { 
     outToClient1.writeObject(gameField); 
     outToClient2.writeObject(gameField); 
     while(true) 
     { 
      try { 
       System.out.println("listening to "+client1.getNickname()); 
       Object o1=inFromClient1.readObject();//read move from client 1.**//StreamCorruptedexception** 

       while(!(o1 instanceof PlayerMove)) 
       { 
        o1=inFromClient1.readObject();//read move from client 1. 
       } 
       PlayerMove move1=(PlayerMove)o1; 
       System.out.println("received move "+move1+" sending to "+client2.getNickname()); 
       outToClient2.writeObject(move1); 
       System.out.println("listening to "+client2.getNickname()); 
       Object o2=inFromClient2.readObject();//read move from client 1. 
       while(!(o2 instanceof PlayerMove)) 
       { 
        o2=inFromClient2.readObject();//read move from client 1. 
       } 
       PlayerMove move2=(PlayerMove)o2; 
       System.out.println("received move "+move2+" sending to "+client1.getNickname()); 
       outToClient1.writeObject(move2); 
      } 
       catch (ClassNotFoundException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } 
     } 
    } catch (IOException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 

} 
}  

i sorunu sanmıyorum gerçi model.addClient yöntemi burada

public void addClient(String nickname, Socket  clientSocket,ObjectOutputStream stream,ObjectInputStream inStream) 
{ 
    clients.addClient(nickname, clientSocket,stream,inStream);//add to arraylist 
//send client list to all clients 
    String[] users=this.getAvailableClients(); 
    ObjectOutputStream[] streams=clients.getOutStreams(); 
    for(int i=0;i<streams.length;i++) 
    { 
     try { 
      streams[i].writeObject(users); 
     } catch (IOException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
    } 
} 

sunucuya nesneleri gönderir istemci tarafı proxy, yöntemleri kullanıcı eylemleri tarafından tetiklenen GUI

public class Proxy { 
final int PORT = 1337; 
String host; 
String nickname; 
private Socket clientSocket; 
private ObjectOutputStream outToServer; 
private ObjectInputStream inFromServer; 
private ClientModelManager manager; 
public Proxy(String nickname,String host,ClientModelManager manager) 
{ 
    this.nickname=nickname; 
    this.host=host; 
    this.manager=manager; 
    this.connect(nickname); 
} 
public void connect(String nick) 
{ 
    Socket clientSocket; 
    try { 
     clientSocket = new Socket(host, PORT); 
     System.out.println("client socket created"); 
     outToServer = new ObjectOutputStream(clientSocket.getOutputStream()); 
     inFromServer=new ObjectInputStream(clientSocket.getInputStream()); 
     outToServer.flush(); 
     outToServer.writeObject(nick); 
     ClientReceiverThread t=new ClientReceiverThread(inFromServer,manager); 
     t.start(); 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
} 
public void makeRequest(String user) 
{ 
    try 
    { 
    outToServer.writeObject(new RequestForGame(user)); 
    } 
    catch(IOException e) 
    { 
     e.printStackTrace(); 
    } 
} 
public void quit() 
{ 
    try { 
     outToServer.writeObject(new String("i want to quit")); 
     //clientSocket.close(); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 
} 
public void sendMove(PlayerMove move) 
{ 
    try { 
     outToServer.writeObject(move); 
    } catch (IOException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 
} 

}

+0

ServerModelManager, 'model.addClient (rumuz, bağlantıSocket, outToClient, inFromClient) 'i çağırdığınızda ne yapıyor? İçinde akışı bozan bir kod olabilir. – Vulcan

+0

addClient (kullanıcıyı, soket, objektekutusu ve girdi akışını tutan ClientRepresantative bir ArrayList'e ekler.) Hiçbir şey okumadı – user1420273

+0

Tamam. Ayrıca, üstbilginin gönderilmesini sağlamak için bunları oluşturduktan sonra ObjectOutputStreams öğesini temizlemelisiniz. Bu hatayı almanızın nedeni olabilir; Akış başlığı henüz geçmedi. ObjectOutputStream'i, oluşturulduktan sonra hem istemcide hem de sunucuda yıkayın. – Vulcan

cevap

6

Bu sorun eğer ortaya çıkabilir soketin ömrü için aynı olanları kullanmak yerine, aynı soket üzerinden yeni bir ObjectInputStream veya ObjectOutputStream inşa edersiniz; Aynı soketten başka bir akım kullanırsanız; veya nesne olmayan bir nesneyi okumak veya yazmak için nesne akışlarını kullanırsanız ve senkronizasyondan çıkarsanız.

+1

Önce ObjectOutputStream'i her iki tarafta (Proxy, ServerCommunicationThread) oluşturuyorum. Ben sadece bir kere yapıyorum ve sonra sadece diğer Konuya bir referans gönderin. Başka türlü bir akış kullanmıyorum. Akla gelen tek şey, aynı anda 2 Threads aynı ObjectInputStream bir nesneyi okumaya çalışıyorum (ServerCommunicationThread, ServerGameThread) Bu sorun olabilir mi? (istisna yerine o kadar ki ...) – user1420273

+0

@ user1420273 Uygun senkronizasyonunuz olmadıkça, kesinlikle bunu yapabilir. – EJP

3

Bu, seri hale getirilmiş nesneyi okuyan JVM nesnesi için doğru sınıf/jar dosyalarına sahip değilse de oluşabilir. Bu genellikle ClassNotFoundException ile sonuçlanır, ancak farklı jar/sınıf sürümleriniz varsa ve serialVersionUID sürümleri arasında değiştirilmediyse, StreamCorruptedException üretilir. (Bu istisna, eğer bir sınıf adı çatışması varsa, mümkün olabilir: ör. Aynı tam sınıfa sahip farklı bir sınıf içeren bir kavanoz, muhtemelen aynı serilVersionUID'a da ihtiyaçları vardır).

İstemci tarafının doğru jar ve sınıf sürümlerine sahip olduğunu doğrulayın. ObjectInputStream sonra sadece bir kez inşa ve varsa

+0

Hayır yapamaz. Bu durum bir ClassNotFoundException neden olur. – EJP

+1

Bu yanıtı, doğru jar dosyaları yükleyerek sorudaki hatayı başarıyla düzeltmiş gibi yaptım. Davalarıma inanıyorum ki yanlış sürümlerim vardı (ve UID'nin uygun şekilde bakımı yapılmamıştı), ancak bir süre önce olsa da ... Sınıf adı çatışmalarıyla da mümkün olabilir mi? @ejp Ben jar dosya sürümlerini belirtmek için cevabımı değiştireceğim - aşağı oyınızı kaldırmak için ücretsiz düştü, başkalarının deneyimlerinden fayda sağlamak için birisini motive etmiyor! Eğer bir 'serialVersionUID' uyuşmazlığı varsa – drevicko

+0

açıkça listeleyen öyle diyor istisna almak hem beklenen ve' fiili Sen 'beklenmedik türü kodu 0x00.' Mis-tanı değiller diyen bir' StreamCorruptedException' alamadım serialVersionUIDs.' kimseye faydalı değil. – EJP

2

tam o sırada sadece tek iplik bir anda bu nesneye erişebilen emin olmak için synchronized bloğunun içinde bu nesnenin erişime içine diğer Konuya bunun bir referans geçti.

ObjectInputStream'dan okurken, birden çok iş parçacığı arasında paylaşılıyorsa, synchronized bloğunun içine erişin.


örnek kod: Ben bu yöntemi ekleyerek bir sınıf için özel bir seri kaldırma rutin uygulamak durumunda nereye karşılaştım Bir ihtimal daha var

... 
String nickname = null; 
synchronized (inFromClient) { 
    nickname = (String) inFromClient.readObject(); 
} 
3

(readObject() tüm oluşumları için bunu): daha fazla uygun şekilde o başlatmak için giriş akımının okumadan önce

private void readObject(ObjectInputStream objectInputStream) throws IOException 

sonra objectInputStream.defaultReadObject() olarak adlandırılır ve adı olmalıdır Nesne.

Bunu özledim ve bir istisna olmaksızın geri dönen nesneye rağmen, geçersiz tür kod istisnasını kafa karıştırıcı olarak yükselten nesne akışının bir sonraki okumasıydı.

Bu bağlantı, http://osdir.com/ml/java.sun.jini/2003-10/msg00204.html adresindeki süreç hakkında daha fazla bilgi sağlar.

+0

Bu, sorunun doğru bir ifadesi değil. Sorun, defaultReadObject() işlevini çağırmanız gerektiğidir. Bunu yaptıktan sonra, kendi öğelerinizin bayt sayısını tam olarak okumanız önemli değildir. – EJP

+0

Düzeltmeler eklendi. – user2219808

2

Bu istisnayı da yaptım. Sunucu sınıfı ve istemci sınıfı için iki iş parçacığı kullandığımdan oluştu. Nesne gönderme ve alma için bir iplik kullandım. Sonra tamam oldu. Bu, synchronized ile aşina değilseniz, sorunu çözmek için kolay bir yoldur.

1

java.io.StreamCorruptedException: geçersiz türü kodu: 00

Geçenlerde olsa ne yaptığını OP yapmıyor, bu sorunla karşılaştık. Hızlı bir google araması yaptım ve çok yardımcı olan bir şey bulamadım ve çözdüğümü düşündüğümden çözümümle ilgili bir yorum yapıyorum.

TLDR: Aynı çıktı akışına aynı anda birden çok ileti yazmamış (bunun yerine sırayla). İstemci tarafı verileri okumayı denediğinde sorunlara neden olur. Çözüm çıktıya yazma üzerinde bir kilit koyuyor.

Çok oyunculu (istemci-sunucu modeli) oyunu yapmak için OP'ye çok benzer bir şey yapıyorum. Trafik dinleyen OP gibi bir iş parçacığım var. Neler oluyordu, sunucu tarafımda, sunucunun aynı anda bir müşterinin akışına yazdığı birden fazla iş parçacığı vardı (bunun mümkün olduğunu düşünmedim, oyun yarı sıra tabanlıydı). Gelen trafiği okuyan istemci tarafı iş parçacığı bu istisnayı fırlatıyordu. Bunu çözmek için temel olarak istemcinin akışına (sunucu tarafında) yazılan parçaya bir kilit koydum, böylece sunucu tarafındaki her iş parçacığı, akışa yazmadan önce kilidi almalıdır.

İlgili konular