ObjectInputStream/ObjectOutputStream work not righ

2020-02-07 07:10发布

问题:

I have classes: Client, Server and Background is working with Player class. I really don't understand why my Client class with ObjectInputStream/ObjectOutputStream doesn't work right.

What i'm doing bad? Where's my mistake?

package Shooter2Dv27082013;
public class Player implements Serializable{
....
public int x=10;
public int y=10;
.... }

package Shooter2Dv27082013;
public class Background extends JPanel implements ActionListener, Serializable {
public int countCollisions=0;
private int time = 20;                       // 0.02s
Timer mainTimer = new Timer(time, this);
....
Player p = new Player(); ... }

And now Client class:

package Shooter2Dv27082013;


import javax.swing.*;
import java.net.*;
import java.io.*;

public class Client {
    public static void main(String[] ar) {
        JFrame frame = new JFrame("D2 Shooter");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(1000, 520);
        Background bg = new Background();
        frame.add(bg);
        frame.setResizable(false);
        frame.setVisible(true);

        int serverPort = 6666; 
        String address = "127.0.0.1"; /

        Player p = new Player();
        try {
            InetAddress ipAddress = InetAddress.getByName(address); 
            System.out.println("Any of you heard of a socket with IP address " + address + " and port " + serverPort + "?");
            Socket socket = new Socket(ipAddress, serverPort); 
            System.out.println("Yes! I just got hold of the program.");

            InputStream sin = socket.getInputStream();
            OutputStream sout = socket.getOutputStream();

            ObjectInputStream ois = new ObjectInputStream(sin);
            ObjectOutputStream oos = new ObjectOutputStream(sout);

            System.out.println("Streams are created. Let's try send these objects");
            System.out.println();


            System.out.println("P.x : "+bg.p.x);
            while (true) {
                oos.writeObject(bg.p);
                oos.flush();
                oos.close();
                System.out.println("Player X: " + bg.p.x + " Player Y: " + bg.p.y);
                p = (Player) ois.readObject();
                ois.close();
                System.out.println("New X: " + p.x + "New Y: "+p.y);
                System.out.println("Looks like the server is pleased with us. Go ahead and enter more lines.");
                System.out.println();
            }

        } catch (Exception x) {
            x.printStackTrace();
        }
    }
}

It doesn't send Object to Server class, but it also says nothing about the error.

Server class:

package Shooter2Dv27082013;

import java.net.*;
import java.io.*;
public class Server {
    public static void main(String[] ar)    {
        int port = 6666; 
        try {
            ServerSocket ss = new ServerSocket(port); 
            System.out.println("Waiting for a client...");

            Socket socket = ss.accept(); 
            System.out.println("Got a client :) ... Finally, someone saw me through all the cover!");
            System.out.println();

            InputStream sin = socket.getInputStream();
            OutputStream sout = socket.getOutputStream();

            ObjectInputStream ois = new ObjectInputStream(sin);
            ObjectOutputStream oos = new ObjectOutputStream(sout);

            Player p = new Player();

            while(true) {
                p = (Player) ois.readObject();
                System.out.println("The client just sent me this x: "+p.x+" y: "+p.y);
                p.x=555; p.y=600;
                System.out.println("I change it and now I'm sending it back...");
                oos.writeObject(p);
                oos.flush();
                oos.close();
                System.out.println("Waiting for the next line...");
                System.out.println();
            }
        } catch(Exception x) { x.printStackTrace(); }
    }
}

回答1:

You are closing the stream in a loop. You can't use a stream or any resource after it has been closed.



回答2:

You need to construct the ObjectOutputStream before the ObjectInputStream, at both ends. At present you have a deadlock.

You also need to move the closes outside the loops.



回答3:

Ok, this is how object streams work and the solution that works everywhere.

Object stream data is preceded by a 4 byte 'magical' sequence AC ED 00 05. An ObjectInputStream will peek for this data at construction time rather than before the first read. And that's logical: one wants to be sure it is a proper stream before being too far in an application. The sequence is buffered by the ObjectOutputStream at construction time so that it is pushed on the stream at the first write. This method often leads to complexities in buffered situations or transferring via pipes or sockets. Fortunately there is a just as simple as effective solution to all these problems:

Flush the ObjectOutputStream immediately after construction!

ObjectOutputStream myStream = new ObjectOutputStream ( anotherStream );
myStream.flush();

In your case in both client and server apps.