I have the following code structure.
A transaction handler of type Transaction which is a field in a Client Handler class, which talks to a Server. (the client handler and the server are collocated), the client talks to the client handler via serialized object messages.
When a new transaction request comes in from the client, (comes on thread using the readObject() method of an object input stream), I then do a series of trx_handler.setFoo(trx.getFoo))). This works fine, I can handle the first request. But when a subsequent request comes in (which only starts getting executed after the first request finished due to the loop structure, I find that the trx handler has been reinitialised to its default values, the object is still there, but all the values inside are the defaut ones. What can cause this problem?
My first guess would be garbage collection, but in my Client Handler class, there is always a pointer to this trx_handler.
The code below illustrates what happens. A statement would first be of type start, so the trx_handler will be correctly initialised. handle_statement will then be called. Subsequent statements should then be received, but at this point the trx_handler has been reinitialised to its default settings, so the access_set field is null, the session id as well, and none of the modification made to the object in hande_statement are visible
Thanks
public class Handler {
private Statement trx_handler;
/* Constructor initialises trx_handler to new Statement(); */
public ClientHandler(final Socket socket, long uid, Server server, ObjectInputStream ois) throws IOException, Exception {
LOGGER.info("Constructing Handler");
this.uid = uid;
this.server = server;
this.socket = socket;
this.database = server.getDB();
this.trx_sys = database.getTransactionManager();
create_listening(socket, ois);
out = socket.getOutputStream();
oos = new ObjectOutputStream(out);
this.trx_handler = new Statement(false);
}
private void create_incoming(final Socket socket, final ObjectInputStream stream) {
Thread incoming = new Thread() {
#Override
public void run() {
ObjectInputStream ois = stream;
InputStream in = null;
while (true) {
Object statement = null;
try {
statement = ois.readObject();
execute_stat(statement, socket, null);
LOGGER.info("Ready to execute next ");
} catch (SocketException e) {
LOGGER.severe("Connection Closed");
return;
} catch (IOException e) {
LOGGER.severe("Connection Closed");
return;
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
String error_message = e.getMessage();
send_error(socket, error_message);
}
}
}
};
incoming.setDaemon(true);
incoming.start();
}
private synchronized void execute_stat(Statement trx) {
if (trx.getTransactionState() == Consts.trx_end) {
trx_sys.commitTransaction(trx_handler);
return;
} else if (trx.getTransactionState() == Consts.trx_start) {
try {
trx_handler.setAccessSet(trx.getAccessSet());
trx_handler.setSession_id(trx.getSession_id());
trx_sys.startTransaction(trx_handler);
handle_statement(socket, trx_handler);
/* TEST HERE THAT FIELDS IN TRX_HANDLER ARE CORRECTLY SET (INCLUDING SOME MODIFIED IN
handle_statement and they are correctly set */
return;
} catch (Exception ex) {
Logger.getLogger(ClientHandler.class.getName()).log(Level.SEVERE, null, ex);
}
}
try {
LOGGER.info("Execute Trx: stat");
/* Can't see modifications made in the start case */
Statement stats = trx.getStatement();
trx_handler.setStatement(stats);
handle_statement(stats, socket, trx_handler);
} catch (Exception e) {
e.printStackTrace();
}
return;
}
You need to either send a brand new object for each transaction, use ObjectOutputStream.writeUnshared(), or else call ObjectOutputStream.reset() between sends.
Related
So basically im writing a client-server multiplayer game.
I have a SeverCommunicationThread that creates a gameThread if he receives a RequestForGame creates a gameThread.
When i send a RequestForGame exception is thrown java.io.StreamCorruptedException: invalid type code: 00
I assume it's because both threads try to read the same ObjectInputStream, I don't have much understanding about how it works, i just know how to use it. Could you help me understand what's the problem and how to fix it?
Thanks :)
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();
}
}
}
the model.addClient method though i don't think the problem is here
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();
}
}
}
The client side proxy that sends objects to server, the methods are triggered by user actions in 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();
}
}
}
This problem can happen if you
construct a new ObjectInputStream or ObjectOutputStream over the same socket instead of using the same ones for the life of the socket;
use another kind of stream over the same socket as well; or,
use the object streams to read or write something that isn't an object and you get out of sync.
This can also happen if the JVM reading the serialized object does not have the correct class/jar files for the object. This usually results in a ClassNotFoundException, but if you have different jar/class versions and the serialVersionUID was not changed between versions, a StreamCorruptedException is produced. (This exception may also be possible if there is a class name conflict. e.g.: a jar containing a different class with the same full class name, though they probably also need the same serilVersionUID).
Check that the client side has the correct versions of jars and class files.
There's another possibility that I ran across where if you implement a custom deserialization routine for a class by adding this method:
private void readObject( ObjectInputStream objectInputStream ) throws IOException
then objectInputStream.defaultReadObject() must be called and called before any further reads of the input stream to properly initialise the object.
I missed this and despite the object returning without an exception being thrown it was the next read of the object stream that confusingly raised the invalid type code exception.
This link provides further information on the process: http://osdir.com/ml/java.sun.jini/2003-10/msg00204.html.
I too had this exception. It occurred because I used two threads for Server class and Client class. I used one thread for object sending and receiving thing. Then it was ok. This is easy way to solve the problem if you are not familiar with synchronized.
If ObjectInputStream is constructed only once and then just passed a reference of it to the other Thread then simply enclose the access of this object inside synchronized block to make sure that only one thread can access this object at a time.
Whenever you are reading from ObjectInputStream just access it inside the synchronized block if it is shared between multiple threads.
Sample code:(do it for all the occurrences of readObject())
...
String nickname = null;
synchronized (inFromClient) {
nickname = (String) inFromClient.readObject();
}
java.io.StreamCorruptedException: invalid type code: 00
I recently ran into this problem, not doing what OP did though. Did a quick google search and didn't find anything that was too helpful and because I think I solved it I am making a comment with my solution.
TLDR: Don't have multiple threads write to the same output stream at same time (instead take turns). Will cause issues for when client side tries to read the data. Solution is putting a lock on the writing to output.
I am doing something very similar to OP, making a multiplayer (client-server model) game. I have a thread like OP that is listening for traffic. What was happening, in my server side was that server had multiple threads that were writing to a client's stream at the same time (didn't think it was possible, game was semi turn base). Client side thread that was reading the incoming traffic was throwing this exception. To solve this I basically put a lock on the part that wrote to the client's stream (on server side) so each thread in server side would have to obtain the lock before writing to the stream.
Edited my question for clarification and code:
My goal is to pass my String data from my background thread, to my main application thread. Any help is appreciated.
Here is the code that creates the main background thread. This is located in my Server.java class
public class Server {
boolean isConnected = false;
Controller controller = new Controller();
public void startHost() {
Thread host = new Thread(() -> {
Controller controller = new Controller();
ServerSocket server = null;
try {
server = new ServerSocket(GeneralConstants.applicationPort);
} catch (BindException e2) {
System.out.println("Port Already in Use!");
} catch (IOException e) {
//do nothing
}
while (true) {
if (server == null) { break; }
try {
Socket client = server.accept();
System.out.println("Client Connected: " + isConnected);
if (!isConnected) {
controller.createClientHandler(client);
isConnected = true;
System.out.println("Client Connected: " + isConnected);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
host.setDaemon(true);
host.start();
}
Here is the code that is then called when a client is connected, located in my Controller.java class.
public synchronized void createClientHandler(Socket client) {
boolean alreadyConnected = false;
if (alreadyConnected) {
//do NOT assign multiple threads for each client
} else {
ClientHandler handleClients = new ClientHandler("client", client);
}
}
The program then creates two background threads for my client, one to manage receiving messages, and sending messages.
public ClientHandler(String name, Socket s) {
clientSocket = s;
clientName = name;
receiveThread = new Thread(this::receive);
sendThread = new Thread(this::send);
connected = clientSocket.isConnected();
receiveThread.start();
sendThread.start();
}
The thread then successfully creates the inputstream and passes the object to my controller. Which then process and grabs a string assigning it to a variable
public synchronized void handleReceivedPacket(String name, BufferedReader in) {
try {
data = in.readLine();
System.out.println("Successfully assigned data to: " + data);
} catch (IOException e) {
System.out.println("Unable to read result data");
}
}
How do I access my String data from the main thread without getting null?
Aka I can call (or something similar)
controller.returnData();
from my main application. From which it'll either return null (no data yet), or actually return my data. Right now, it's always null.
Edit, this is what's actually calling controller.returnData() {
I don't want to paste a massive amount of code for fear of reaching StackOverflow's code limit, so here's my application structure.
My JavaFX creates the scene, and creates a root gridpane, it then calls a method that creates sub gridpanes based the specified input. Aka, a user can press "Main Menu" that calls my method setScene() which removes the current "sub-root" gridpane and creates a "new" scene. Right now, I have a GameBoard.java class which on button press, calls controller.returnData()
PassOption.setOnAction(event -> {
System.out.println(controller.returnData());
});
There is no functional purpose for this besides testing. If I can receive the data, then I can expand on this using the data.
Start thinking about design. In network applications you typically have to manage the following responsibilites:
Connected clients and their state (connection state, heartbeats, ...)
Received messages from the clients
Messages to transmit to the clients
It makes sense to separate those responsibilities in order to keep the code clean, readable and maintainable.
Separation can mean both, thread-wise and class-wise.
For example, you could implement it as follows:
The class ClientAcceptor is responsible for opening the socket and accepting clients. As soon as a client has connected, it delegates the further work to a controller and then waits for other clients:
public class ClientAcceptor implements Runnable {
#Override
public void run() {
while (true) {
ServerSocket server;
try {
server = new ServerSocket(1992);
Socket client = server.accept();
if (client.isConnected()) {
controller.createClientHandler(client);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
The controller could then create a handler (if the controller decides to do so, e.g. it could also decline the client). The ClientHandler class could look as follows:
public class ClientHandler {
private Thread receiveThread;
private Thread sendThread;
private boolean connected;
private Socket clientSocket;
private String clientName;
private LinkedBlockingDeque<byte[]> sendQueue;
public ClientHandler(String name, Socket s) {
clientSocket = s;
clientName = name;
receiveThread = new Thread(() -> receive());
sendThread = new Thread(() -> send());
connected = clientSocket.isConnected();
receiveThread.start();
sendThread.start();
}
private void receive() {
BufferedInputStream in = null;
try {
in = new BufferedInputStream(clientSocket.getInputStream());
} catch (IOException e) {
connected = false;
}
while (connected) {
try {
byte[] bytes = in.readAllBytes();
if (bytes != null && bytes.length > 0) {
controller.handleReceivedPacket(clientName, bytes);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
private void send() {
BufferedOutputStream out = null;
try {
out = new BufferedOutputStream(clientSocket.getOutputStream());
} catch (IOException e) {
connected = false;
}
while (connected) {
byte[] toSend = sendQueue.getFirst();
if (toSend != null && toSend.length > 0) {
try {
out.write(toSend);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public void send(byte[] packet) {
sendQueue.add(packet);
}
public void close() {
connected = false;
}
}
The ClientHandler is responsible for receiving and transmitting data. If a packet arrives it informes the controller, which parses the packet. The ClientHandler also provides a public API to send data (which is stored in a queue and handled by a thread) and close the connection.
The above code examples are neither tested, nor complete. Take it as a starting point.
I have a Socket that sends a list of Objects every few seconds to a client through ObjectOutputStream. On the server side, after every writeObject(myList) i execute flush then reset. Using VisualVM to check for memory usage, on the server there's no memory leaks, but on the client it seems that the previously read Lists are kept in memory. I tried to execute reset on the ObjectInputStream on the client side but looks like ObjectInputStream does not support this method (it throws a java.io.IOException: mark/reset not supported).
This is my server socket:
public class ConsultaBombas {
public static void inicializarServidorSocket() {
try {
ServerSocket serverSocket = new ServerSocket(5963);
Thread thread = new Thread(() -> {
while (!serverSocket.isClosed()) {
try {
final Socket socket = serverSocket.accept();
new ThreadComunicacao(socket).start();
} catch (Exception e) {
e.printStackTrace();
}
}
});
thread.setName("Consulta bombas (Inicializador)");
thread.start();
} catch (Exception e) {
e.printStackTrace();
}
}
static class ThreadComunicacao extends Thread {
private Socket socket;
public ThreadComunicacao(Socket socket) {
this.socket = socket;
setName("Consulta bombas (Comunicação) com início: " + new SimpleDateFormat("dd/MM/yyyy HH:mm:ss").format(new Date()));
}
#Override
public void run() {
try {
ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());
while (!socket.isClosed()) {
List<Bomba> bombas = new DaoBomba().findAll();
out.writeObject(bombas);
out.flush();
out.reset();
Thread.sleep(1000);
}
} catch (SocketException e) {
if (e.getLocalizedMessage() != null && e.getLocalizedMessage().equalsIgnoreCase("Connection reset by peer: socket write error")) {
System.out.println("Cliente desconectou...");
} else {
e.printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
An this is the client (started with start() method):
public class ConsultaBombasClient {
private Socket socket;
private Thread threadConsulta;
public ConsultaBombasClient(BombasListener bombasListener, String maquinaDestino) {
threadConsulta = new Thread(() -> {
try {
Thread.currentThread().setName("Consulta Bombas");
System.out.println("Endereço bagual: "+maquinaDestino);
socket = new Socket(maquinaDestino, 5963);
ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
Object leitura;
while ((leitura = in.readObject()) != null) {
List<Bomba> bombas = (List<Bomba>) leitura;
bombasListener.run(bombas);
}
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}
});
threadConsulta.setDaemon(true);
}
public void start() {
threadConsulta.start();
}
public interface BombasListener {
void run(List<Bomba> bombas);
}
}
What am i doing wrong?
garbage collection is not immediate, do you have any real memory troubles? Have you tried running the client with low -Xmx value, did you receive the OutOfMemoryError?
– user3707125
You're right, after some time when the memory gets close to the maximum heap size, it clears the objects from memory. I wasn't seeing this because i have a lot of RAM in my pc but with Xmx50m i could see this working as you said. – Mateus Viccari
Clearly bombasListener.run(), whatever it may be, is not releasing the supplied list.
NB ObjectInputStream.readObject() does not return null at end of stream. It is therefore incorrect to use this test as a termination condition for a read loop.
This is a Thread, which handles input and output from the serverside:
public void run() {
Thread currentThread = Thread.currentThread();
while (!currentThread.isInterrupted()) {
SocketChannel socketChannel = null;
try {
socketChannel = serverSocketChannel.accept();
readFromSocket(socketChannel);
} catch (ClosedByInterruptException e) {
// closed due to interrupt
connected = false;
} catch (IOException e) {
if (!isInterrupted()) {
e.printStackTrace();
}
connected = false;
} finally {
quietClose(socketChannel);
}
}
}
/**
* Reads an message from socketChannel and executes
* {#link AbstractServer#handleMessage(String)}. Initializes
* {#link #writer} with the socketChannel.
*
* #param socketChannel
* #throws IOException
*/
public void readFromSocket(SocketChannel socketChannel) throws IOException {
reader = null;
writer = null;
try {
reader = new BufferedReader(new InputStreamReader(socketChannel.socket().getInputStream()));
if (writer == null) {
writer = new PrintWriter(socketChannel.socket().getOutputStream(), true);
}
String message;
while ((message = reader.readLine()) != null) {
handleMessage(message);
}
} catch (ClosedByInterruptException e) {
throw e;
} catch (IOException e) {
e.printStackTrace();
} finally {
quietClose(reader);
quietClose(writer);
}
}
If i call the print-method the thread is getting stucked. Which means the "before" is printed, but the "after" is never reached.
The CheckError method of the printwriter returns false!
/**
* Sends a message to the client.
*
* #param message
*/
public void sendMessage(final String message) {
System.out.println("before");
writer.print(message);
System.out.println("after");
writer.flush();
}
It is in an AbstractServer which is used by two different Servers. The first one was used before already and always worked without a problem (and still does).
The other one is new and causes this problem. It is definitly only one writer for every connection (both localhost with different ports) initialized.
The Client side Datafetcher looks like this:
protected void fetchDataFromSocket() {
if (socketDataFetcher != null) {
socketDataFetcher.interrupt();
}
socketDataFetcher = new Thread(new Runnable() {
#Override
public void run() {
while (!Thread.currentThread().isInterrupted()) {
try {
String message = socketConnection.readLine();
if (messageHandler != null) {
messageHandler.handleMessage(message);
}
} catch (IOException e) {
Thread.currentThread().interrupt();
}
}
}
});
socketDataFetcher.start();
}
Its also pretty much the same as the other one that works with only little changes which actually can't cause the problem.
What could be the reason that the printwriter behaves like this?
edit: If i don't start the socketDataFetcher on the client side, the printwriter is not getting stucked!
While I don't see the declarations, the reader and writer objects (referenced in the readFromSocket() method) look like they might be member variables. I would be concerned about the reader and writer not being thread-safe. I would see about about removing these member variables and see if you still have issues with the writer.
So basically im writing a client-server multiplayer game.
I have a SeverCommunicationThread that creates a gameThread if he receives a RequestForGame creates a gameThread.
When i send a RequestForGame exception is thrown java.io.StreamCorruptedException: invalid type code: 00
I assume it's because both threads try to read the same ObjectInputStream, I don't have much understanding about how it works, i just know how to use it. Could you help me understand what's the problem and how to fix it?
Thanks :)
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();
}
}
}
the model.addClient method though i don't think the problem is here
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();
}
}
}
The client side proxy that sends objects to server, the methods are triggered by user actions in 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();
}
}
}
This problem can happen if you
construct a new ObjectInputStream or ObjectOutputStream over the same socket instead of using the same ones for the life of the socket;
use another kind of stream over the same socket as well; or,
use the object streams to read or write something that isn't an object and you get out of sync.
This can also happen if the JVM reading the serialized object does not have the correct class/jar files for the object. This usually results in a ClassNotFoundException, but if you have different jar/class versions and the serialVersionUID was not changed between versions, a StreamCorruptedException is produced. (This exception may also be possible if there is a class name conflict. e.g.: a jar containing a different class with the same full class name, though they probably also need the same serilVersionUID).
Check that the client side has the correct versions of jars and class files.
There's another possibility that I ran across where if you implement a custom deserialization routine for a class by adding this method:
private void readObject( ObjectInputStream objectInputStream ) throws IOException
then objectInputStream.defaultReadObject() must be called and called before any further reads of the input stream to properly initialise the object.
I missed this and despite the object returning without an exception being thrown it was the next read of the object stream that confusingly raised the invalid type code exception.
This link provides further information on the process: http://osdir.com/ml/java.sun.jini/2003-10/msg00204.html.
I too had this exception. It occurred because I used two threads for Server class and Client class. I used one thread for object sending and receiving thing. Then it was ok. This is easy way to solve the problem if you are not familiar with synchronized.
If ObjectInputStream is constructed only once and then just passed a reference of it to the other Thread then simply enclose the access of this object inside synchronized block to make sure that only one thread can access this object at a time.
Whenever you are reading from ObjectInputStream just access it inside the synchronized block if it is shared between multiple threads.
Sample code:(do it for all the occurrences of readObject())
...
String nickname = null;
synchronized (inFromClient) {
nickname = (String) inFromClient.readObject();
}
java.io.StreamCorruptedException: invalid type code: 00
I recently ran into this problem, not doing what OP did though. Did a quick google search and didn't find anything that was too helpful and because I think I solved it I am making a comment with my solution.
TLDR: Don't have multiple threads write to the same output stream at same time (instead take turns). Will cause issues for when client side tries to read the data. Solution is putting a lock on the writing to output.
I am doing something very similar to OP, making a multiplayer (client-server model) game. I have a thread like OP that is listening for traffic. What was happening, in my server side was that server had multiple threads that were writing to a client's stream at the same time (didn't think it was possible, game was semi turn base). Client side thread that was reading the incoming traffic was throwing this exception. To solve this I basically put a lock on the part that wrote to the client's stream (on server side) so each thread in server side would have to obtain the lock before writing to the stream.