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(); }
}
}
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 theObjectOutputStream
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!In your case in both client and server apps.
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.
You are closing the stream in a loop. You can't use a stream or any resource after it has been closed.