13

つまり、基本的にはクライアントサーバーのマルチプレイヤーゲームを書いています。RequestForGame を受け取った場合に gameThread を作成する SeverCommunicationThread が gameThread を作成します。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();
    }
}

}

4

6 に答える 6

9

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

  • ソケットの存続期間中、同じソケットを使用する代わりに、新しいソケットObjectInputStreamまたはObjectOutputStream同じソケットを構築します。
  • 同じソケットで別の種類のストリームも使用します。また、
  • オブジェクト ストリームを使用してオブジェクトではないものを読み書きすると、同期が取れなくなります。
于 2012-05-27T23:20:00.563 に答える
4

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

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

于 2012-11-07T04:14:53.750 に答える
3

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

private void readObject( ObjectInputStream objectInputStream ) throws IOException

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

私はこれを見逃しており、例外がスローされずにオブジェクトが返されたにもかかわらず、無効な型コード例外を紛らわしく発生させたのは、オブジェクトストリームの次の読み取りでした。

http://osdir.com/ml/java.sun.jini/2003-10/msg00204.htmlのリンクで、プロセスに関する詳細情報を確認できます。

于 2014-12-21T01:47:36.027 に答える
2

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

複数のスレッド間で共有されている場合はObjectInputStream、ブロック内でアクセスするだけです。synchronized


サンプル コード:( のすべての出現に対して実行しますreadObject())

...
String nickname = null;
synchronized (inFromClient) {
    nickname = (String) inFromClient.readObject();
}
于 2014-05-10T12:04:53.657 に答える