2 player applet - server keeps dropping client.

I have a simple server that accepts two connections, relays coordinate info to each. i've a small class SpriteData which is just a couple fields (Point position, double angle, double speed, boolean missile). i thought an object stream would be perfect. the game works fine as long as only one person is moving at a time; but if both players move, crash!

here's my server:

import java.io.*;

import java.net.*;

import java.awt.Point;

publicclass SpriteServer{

public SpriteServer()throws IOException{

SpriteData homeOne=new SpriteData(new Point(50,50),45,0,false);

SpriteData homeTwo=new SpriteData(new Point(518,518),235,0,false);

ServerSocket server =new ServerSocket(9898);

while(true){

Socket clientOne = server.accept();

Socket clientTwo = server.accept();

//notice that the streams are crossed here, so each thread is listening to one and talking on the other

SpriteManager managerOne =new SpriteManager(clientOne,clientTwo,homeOne,homeTwo);

managerOne.start();

SpriteManager managerTwo =new SpriteManager(clientTwo,clientOne,homeTwo,homeOne);

managerTwo.start();

}

}

publicstaticvoid main(String[] args)throws IOException{

System.out.println("this puppy is loaded");

new SpriteServer();

}

}

class SpriteManagerextends Thread{

protected Socket socket;

protected ObjectInputStream in;

protected ObjectOutputStream out;

privateboolean threadStop=false;

String name;

SpriteData home, nmeHome;

Socket mySocket;

public SpriteManager(Socket mySock,Socket nmeSocket, SpriteData homepoint, SpriteData nmeHomepoint)throws IOException{

mySocket=mySock;

home=homepoint;

nmeHome=nmeHomepoint;

try{

in =new ObjectInputStream(mySocket.getInputStream());

out =new ObjectOutputStream(nmeSocket.getOutputStream());

out.flush();

System.out.println("in and out established for tank at "+mySocket.getInetAddress());

out.writeObject(home);

out.flush();

out.writeObject(nmeHome);

}catch(IOException except){

System.out.println("input or output connection not established");

System.exit(-1);

}

}

publicvoid run(){

name = mySocket.getInetAddress().toString();

try{

System.out.println("SpriteServer: "+name+" has arrived.");

while(!threadStop){

out.writeObject(in.readObject());

out.flush();

Thread.sleep(10);

}

}catch(Exception except){

System.out.println("failed communication with " + name);

}finally{

threadStop=true;

try{

mySocket.close();

System.out.println("closing socket for "+name);

}catch(IOException ex){

System.out.println("failed at closing bad socket " + name);

}

}

}

}

does anyone see what could be the problem? why is it dropping the connection? is this just not a sound way to accomplish 1 on 1 gaming?

[5592 byte] By [outawatera] at [2007-9-28 9:56:18]
# 1
What does a "crash" look like? A thrown exception, or deadlock?If it's an exception, you should include it with your posting.If it's deadlock, then how do you know the problem is not with the client?
JN_a at 2007-7-11 23:28:42 > top of Java-index,Other Topics,Java Game Development...
# 2

example:

2 players. each can see his own tank and the other moving about and firing missiles. the server will lose connection with a client. if it drops player one's connection, then player one will be fine, and still see his and the other tank moving, but player two will no longer see player one's tank move, as player one is no longer sending coordinates. i'm not really sure if it's the client or the server...

outawatera at 2007-7-11 23:28:42 > top of Java-index,Other Topics,Java Game Development...
# 3
connections don't just disappear :-\ there's got to be a deadlock or exception being thrown. in order to narrow down your options, you need to at least know what software is causing the problem
markuskidda at 2007-7-11 23:28:42 > top of Java-index,Other Topics,Java Game Development...
# 4
after further investigation, it appears that the client may be throwing an EOFException, which is strange, as i'm reading no files. the client uses ObjectOutputStream and ObjectInputStream for communication with the server.
outawatera at 2007-7-11 23:28:42 > top of Java-index,Other Topics,Java Game Development...
# 5

these two classes may help:

/**

* @author Mark W. Kidd

*

* ObjectInStream is a trivial subclass of ObjectInputStream necessary to override the

* readStreamHeader() method

*/

class ObjectInStream extends java.io.ObjectInputStream {

public ObjectInStream(InputStream in) throws IOException {

super(in);

}

/**

* Empty implementation so that ObjectInStream does not attempt to read a stream

* header.

* @see java.io.ObjectInputStream#readStreamHeader()

*/

protected void readStreamHeader() throws IOException, StreamCorruptedException {}

}

import java.io.*;

/**

* @author Mark W. Kidd

*

* ObjectOutStream is a trivial subclass of ObjectOutputStream used to remove the stream

* headers which can cause successively written Objects to be decoded incorrectly

*/

class ObjectOutStream extends java.io.ObjectOutputStream {

public ObjectOutStream(OutputStream out) throws IOException {

super(out);

}

/**

* Empty implementation so that no stream header is written

* @see java.io.ObjectOutputStream#writeStreamHeader()

*/

protected void writeStreamHeader() throws IOException, StreamCorruptedException {}

}

Use them instead of the standard ones. For an explanation of why, just search the forums for something like "writeStreamHeader() objectoutputstream." Hopefully that will help.

markuskidda at 2007-7-11 23:28:42 > top of Java-index,Other Topics,Java Game Development...
# 6
and on even further investigation, the server throws a classnotfoundexception. what a shame. so if i put the class file for the data object (SpriteDate) in the same directory as the server, everything works fine. silly strange. why would the server need to know what it was relaying?
outawatera at 2007-7-11 23:28:42 > top of Java-index,Other Topics,Java Game Development...
# 7
What are you using on the server side to transport this data?
markuskidda at 2007-7-11 23:28:42 > top of Java-index,Other Topics,Java Game Development...
# 8

I'm using ObjectOutputStream on the client end as well. like i said, it works fine as long as it has access to a definition of the class being transmitted. i just don't see why the server needs to know what object is being manipulated by

something like

out.writeObject(in.readObject());

outawatera at 2007-7-11 23:28:42 > top of Java-index,Other Topics,Java Game Development...
# 9
Because you're deserializing it when you call in.readObject(). You should just be able to use regular InputStreams and OutputStreams to transfer the data since the server doesn't need to interact with it.
markuskidda at 2007-7-11 23:28:42 > top of Java-index,Other Topics,Java Game Development...
# 10
a ha!!!!!!!! that is exactly what i was looking for! i agree, that should work great. i'll let you know pronto. brb
outawatera at 2007-7-11 23:28:42 > top of Java-index,Other Topics,Java Game Development...
# 11
oops. those guys are abstract and cannot be instantiated. :(
outawatera at 2007-7-11 23:28:42 > top of Java-index,Other Topics,Java Game Development...
# 12

alright, it works not, using

in = new ObjectInputStream(mySocket.getInputStream());out = new ObjectOutputStream(nmeSocket.getOutputStream());

but the motion is very, very choppy. not running nearly as well as it did wth the ObjectInput and ObjectOutput streams. any ideas?

outawatera at 2007-7-11 23:28:42 > top of Java-index,Other Topics,Java Game Development...
# 13
what a terrible typo. that is it works NOW but the motion is choppy. one letter can make all the difference, sometimes.
outawatera at 2007-7-11 23:28:42 > top of Java-index,Other Topics,Java Game Development...
# 14
well, i tried a BufferedInputStream and BufferedOutPutStream, but they show very very poor performance. looks like i'm just going to have to include the SpriteData.class with the server. what a shame. can anyone think of a better way to resolve this? I'm all ears.
outawatera at 2007-7-11 23:28:42 > top of Java-index,Other Topics,Java Game Development...
# 15
Have you tried it with just regular Input- and OutputStreams? If that doesn't work, I've had some luck in the past with just buffering output.
markuskidda at 2007-7-18 20:03:05 > top of Java-index,Other Topics,Java Game Development...
# 16
and of course if you use any buffering, you have to flush it regularly
markuskidda at 2007-7-18 20:03:05 > top of Java-index,Other Topics,Java Game Development...
# 17

i'm currently using

in = new BufferedInputSream(socket.getInputStream());

out = new BufferedOutputStream(socket.getOutputStream());

out.write(in.read());

but i did forget to flush "out". i'll try that later today and post the results. thank for the help so far, mark. i stare at the screen so long, that i can get stuck on the simplest things sometimes.

outawatera at 2007-7-18 20:03:05 > top of Java-index,Other Topics,Java Game Development...
# 18

I've found that the javadocs and the tutorial often don't fully prepare you for the idiosyncracies of IO. Sometimes I end up just trying different combinations. Right now I'm debugging an issue with buffered streams myself (albeit it seems unrelated). The documentation seems to suggest that buffering is the greatest thing in the world, but despite Sun's comments otherwise, sometimes it's less appropriate than others.

Let me know if there's anything else I can do.

markuskidda at 2007-7-18 20:03:05 > top of Java-index,Other Topics,Java Game Development...
# 19
after rebooting my server, recompiling and reloading, it seems to be working much better. i haven't really had a chance to test the game yet with remote computers, but it seems to be fine on my LAN. i wonder if the performance will be similar over the internet.
outawatera at 2007-7-18 20:03:05 > top of Java-index,Other Topics,Java Game Development...