web-dev-qa-db-ja.com

java.io.StreamCorruptedException:無効なタイプコード:00

つまり、基本的にはクライアントサーバーマルチプレイヤーゲームを書いています。 RequestForGameを受信するとgameThreadを作成するSeverCommunicationThreadがあります。 RequestForGame例外を送信すると、Java.io.StreamCorruptedExceptionがスローされます:無効なタイプコード:00両方のスレッドが同じObjectInputStreamを読み取ろうとしているためだと思いますが、その仕組みについてはよくわかりません。使用方法を知っているだけです。それ。問題の内容とその修正方法を理解するのを手伝ってもらえますか?ありがとう:)

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

}
}    

model.addClientメソッドですが、問題はここにあるとは思いません

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

オブジェクトをサーバーに送信するクライアント側プロキシ。メソッドは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();
    }
}

}

12
user1420273

この問題は、次の場合に発生する可能性があります

  • ソケットの存続期間中、同じソケットを使用する代わりに、同じソケット上に新しいObjectInputStreamまたはObjectOutputStreamを作成します。
  • 同じソケットで別の種類のストリームも使用します。または、
  • オブジェクトストリームを使用して、オブジェクトではないものを読み書きすると、同期がとれなくなります。
6
user207421

これは、シリアル化されたオブジェクトを読み取るJVMにオブジェクトの正しいクラス/ jarファイルがない場合にも発生する可能性があります。これにより、通常はClassNotFoundExceptionになりますが、jar /クラスのバージョンが異なり、バージョン間でserialVersionUIDが変更されていない場合は、StreamCorruptedExceptionが生成されます。 (この例外は、クラス名の競合がある場合にも発生する可能性があります。たとえば、同じ完全なクラス名を持つ異なるクラスを含むjarですが、おそらく同じserilVersionUIDも必要です)。

クライアント側に正しいバージョンのjarファイルとクラスファイルがあることを確認してください。

4
drevicko

このメソッドを追加してクラスのカスタム逆シリアル化ルーチンを実装すると、私が遭遇した別の可能性があります。

private void readObject( ObjectInputStream objectInputStream ) throws IOException

次に、オブジェクトを適切に初期化するために、入力ストリームをさらに読み取る前に、objectInputStream.defaultReadObject()を呼び出して呼び出す必要があります。

私はこれを見逃し、例外がスローされずにオブジェクトが戻ってきたにもかかわらず、オブジェクトストリームの次の読み取りが、混乱して無効なタイプコード例外を発生させました。

このリンクは、プロセスに関する詳細情報を提供します: http://osdir.com/ml/Java.Sun.jini/2003-10/msg00204.html

3
user2219808

私もこの例外がありました。これは、サーバークラスとクライアントクラスに2つのスレッドを使用したために発生しました。オブジェクトの送受信に1つのスレッドを使用しました。それからそれは大丈夫だった。 synchronizedに慣れていない場合、これは問題を解決する簡単な方法です。

2
Lasitha Yapa

ObjectInputStreamが1回だけ作成され、その参照を他のスレッドに渡した場合は、このオブジェクトへのアクセスをsynchronizedブロック内に囲み、1つのスレッドのみがこのオブジェクトにアクセスできるようにします。一度に。

ObjectInputStreamから読み取るときはいつでも、複数のスレッド間で共有されている場合は、synchronizedブロック内でアクセスするだけです。


サンプルコード:(readObject()のすべてのオカレンスに対して実行します)

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

Java.io.StreamCorruptedException:無効なタイプコード:00

私は最近この問題に遭遇しましたが、OPが行ったことをしていませんでした。簡単なグーグル検索をしましたが、あまりにも役立つものは見つかりませんでした。私はそれを解決したと思うので、私の解決策についてコメントしています。

TLDR:複数のスレッドが同じ出力ストリームに同時に書き込むことはありません(代わりに交代で)。クライアント側がデータを読み取ろうとしたときに問題が発生します。解決策は、出力への書き込みをロックすることです。

私はOPと非常によく似た何かをしていて、マルチプレイヤー(クライアントサーバーモデル)ゲームを作っています。トラフィックをリッスンしているOPのようなスレッドがあります。私のサーバー側で起こっていたのは、サーバーに同時にクライアントのストリームに書き込んでいる複数のスレッドがあったことでした(それが可能だとは思わなかった、ゲームは半ターンベースでした)。着信トラフィックを読み取っていたクライアント側スレッドがこの例外をスローしていました。これを解決するために、基本的にクライアントのストリーム(サーバー側)に書き込む部分にロックを設定し、サーバー側の各スレッドがストリームに書き込む前にロックを取得する必要があるようにします。

1
BWC semaJ