I'm writting a local-network based multiplayer game. Therefore I have to send the "player object" via sockets from the one program to the other one and the other way round. Because I don't want to slow down or to complicate the thread, which update and render the game, I create a "server thread" and a "client thread", which communicate with each other all the time. The attributes of the player object change very often (for example when you move). So I added a update methode to the two new threads, which import the changing player object from the main class.
The code for the server thread:
import java.net.; import java.io.;
public class Server implements Runnable {
ServerSocket serverSocket;
Socket clientSocket;
ObjectOutputStream out1;
ObjectInputStream in1;
Player myPlayer;
Player yourPlayer;
public Server(int portNumber){
try {
serverSocket = new ServerSocket(portNumber);
clientSocket = serverSocket.accept();
out1 = new ObjectOutputStream(clientSocket.getOutputStream());
in1 = new ObjectInputStream(clientSocket.getInputStream());
myPlayer = new Player(100, 100);
myPlayer.init(100, 100);
out1.writeObject(myPlayer);
}catch(IOException e){
System.err.println(e.getMessage());
}
}
public void run(){
while(true) {
try {
yourPlayer = (Player) in1.readObject();
out1.writeObject(myPlayer);
} catch (IOException e) {
System.err.println("ERROR");
}catch(ClassNotFoundException e){
}
}
}
public void update(Player player){
myPlayer = player;
}
public Player getYourPlayer() {
return yourPlayer;
}
}`
The problem is: the recieved objects don't change, although the original player objects change. Is it because the update method called by the main class doesn't work parallel to the ever lasting while loop in the run method?? I really have no idea.. :( please help
The problem is: the recieved objects don't change, although the original player objects change.
I believe the problem exists in the way you are writing objects to the stream. Each time you call out1.writeObject(myPlayer)
, you should also call out1.flush()
and output.reset()
. The call to flush()
will ensure that if you end up doing any buffering on the output stream, any buffered unwritten bytes will be written.
The reset()
call is a little more complicated in what it does under the hood. Your output stream will maintain a listing of all the objects it has written already. If you write your myPlayer
object a second time without resetting the stream, the stream will think it has already sent it and tell the client to use the previously-received version of that object instead, making it appear to your client that it's getting the same object every time.
The reason behind this is to save bandwidth in the case where the same identical object is written many times. For instance, let's say myPlayer
had a complicated object hierarchy that pointed to a second object myObject
in a bunch of different places in myPlayer
's reference graph. You wouldn't want to write myObject
every time you saw it in that case, so ObjectInput/OutputStreams keep track of what's been received/sent already, and pass around an ID whenever they encounter a duplicate Object reference. Calling reset()
between calls to writeObject(obj)
forces the send/receive state to be cleared each time so that myPlayer
is instead rewritten each time.
Potential Parallel Issue
As others have commented, you are modifying myPlayer
outside of the while
loop that writes it to the socket. This could be dangerous if a modification to myPlayer
happens at exactly the same time it is being written to the socket. You should probably put all accesses to myPlayer
inside synchronized
blocks to prevent concurrent read/write problems.