public class RMIClient {
public static void main(String[] args) {
String serverURL = "rmi://" + args[0] + "/GameServer";
String viewURL = "rmi://" + args[0] + "/ViewServer";
try {
GameInterface gameIntf = (GameInterface)Naming.lookup(serverURL);
PlayerView view = (PlayerView)Naming.lookup(viewURL);
while(!gameIntf.getGameOver()){
synchronized(GameInterface.sharedObject){
GameInterface.sharedObject.notify();
System.out.println(view.getMessage());
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
if(br.readLine().contains("y"))
gameIntf.setNextMove(true);
GameInterface.sharedObject.wait();
}
}
} catch (MalformedURLException | RemoteException | NotBoundException e1) {
e1.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public interface GameInterface extends Remote{
public static final Object sharedObject = new Object();
public void setNextMove(boolean val) throws RemoteException;
public boolean getGameOver() throws RemoteException;
}
Currently when I start rmiregistry, server and start two RMI clients, both clients wait forever after getting 1st input i. e. one client is not notifying other. I am starting RMI clients on same JVM.
No. The stub object at the client is not the same Java object as the remote server in the server host, and synchronizing on it or notifying it doesn't magically propagate across the network to the server or to other clients.
The answers in the link you cited don't support your theory either. You need to read the answers by #MarcH and me, and ignore the others, which are wrong in various ways.
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.
I'm new to Java socket programming and I'm trying to write a program which is supposed to be run on 2 separate controllers. I have written a thread which is used as the communication class.
I have defined a flag called SFlag so that when the value of this flag is changed to 1 anywhere in my program, the corresponding controller will send a hello message to the other controller through sendPackets() function. The other controller will receive this message through ReceivePackets class and it will print the result. Here is the code:
// My UDP communication class
public class MainConn implements Runnable {
// Sockets, 1 for sending, and one for receiving
DatagramSocket socket1, socket2;
// localIP
private InetAddress localIP;
private InetAddress leaderIP;
// classes to run on separate Threads
private ReceivePackets rcvThread;
#Override
public void run() {
process();
}
public void process() {
// initialize some parameters
init1();
// Make Thread for receiving packets and update counters from all
// controller
rcvThread = new ReceivePackets();
Thread r = new Thread(rcvThread);
r.start();
sendPackets();
}
public void init1() {
try {
// create sockets
String tempString = config.get("localPort");
localPort = Integer.parseInt(tempString);
logger.info("----------here is==========" +localPort);
leaderIP = InetAddress.getByName("127.0.0.1");
logger.info("----------here is==========" +leaderIP);
socket1 = new DatagramSocket(localPort); // for sending
socket2 = new DatagramSocket(localPort + 1); // for receiving
} catch (SocketException | UnknownHostException e) {
e.printStackTrace();
}
}
//*******************************************************
public void sendPackets() {
// will be used to begin sending message type II after 3*hello
// period
while (true) {
try {
// if network not converged, send message type I, contains:
// type number (1) then
if (SFlag == 1) {
logger.info("Sending the message");
String tempString = new String("Hello");
byte[] data = tempString.getBytes();
DatagramPacket sentPacket = new DatagramPacket(data, tempString.length());
sentPacket.setAddress(leaderIP);
sentPacket.setPort(20222);
socket1.send(sentPacket);
SFlag = 0;
}
else {
logger.info("Nothinggggggggggggg");
}
Thread.sleep(5000);// wait for Hello period
} catch (SocketException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
catch(Exception e){
e.printStackTrace();
}
}
}
class ReceivePackets implements Runnable {
#Override
public void run() {
try {
while (true) {
logger.info("---------------waiting------------------");
byte[] data = new byte[1000];
DatagramPacket receivedPacket = new DatagramPacket(data, data.length);
socket2.receive(receivedPacket);
String senderIP = receivedPacket.getAddress().getHostAddress();
String senderPort = "" + receivedPacket.getPort();
String message = new String(data, 0, receivedPacket.getLength());
logger.info(message);
System.out.println("Received Message: "+message);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
When the value of SFlag is changed to 1, it seems that the first controller is sending the message ("Sending the message" is printed), but there seems to be a problem with receiving the message on the second controller, because the received message is not printed.
What is the problem?
There are some issues with your code:
(1) Since both threads rely on SFlag for communication, make sure it is declared with the volatile keyword:
private volatile int SFlag = 0;
The volatile keyword prevents the variable from being cached, so both threads will see the same value all the time. Besides that, reading and writing operations on volatile variables are atomic.
(2) You have a hardcoded port number in this line:
sentPacket.setPort(20222);
Make sure this is the port number used by the ReceivePackets thread. Ideally we should never have magic numbers mixed with the code. So you should move that port number to a separate variable or constant.
(3) In Java you shouldn't create a String with new. For example, this is bad practice:
String tempString = new String("Hello"); // bad practice
You should do:
String tempString = "Hello";
My last piece of advice is: clean up your code. You can look at Oracle's tutorial on sending and receiving datagram packets here: https://docs.oracle.com/javase/tutorial/networking/datagrams/clientServer.html
I'm relatively new to Java and I'm writing an application to interrogate an Apache HTTP server's access_log file; with this, I want to submit the IP Addresses individually (probably via the Apache HTTPClient library) to another Java instance on another server (as the Web server does not have FTP enabled) to pull some log files. At the moment I've managed to bumble my way through modifying a 'tail -f' equivalent class to suit the programs needs and then manipulate that data to get the IP Addresses that I need to do something with - I even managed to make the 'tail' class threaded so it could address multiple periods of time!
With that said, I want to use a for loop to iterate through each entry in my computerRebootList String Array and with each address create a thread to perform some more work but all I can think of is this;
for (String tmpIpAddress : computerRebootList ) {
ComputerIpHandler handler = new ComputerIpHandler();
}
and then create another class named ComputerIpHandler like so;
public class KioskIpHandler implements Runnable {
static final Logger logger = LogManager.getLogger( ComputerIpHandler.class );
#Override public void run() {
//do some code
}
public static void main(String computerIp) {
Thread mainThread = new Thread(new ComputerIpHandler());
mainThread.start();
try {
logger.info("log some stuff");
mainThread.join();
logger.info("yay it's done");
}
catch (InterruptedException errInterrupted) {
logger.error(errInterrupted.getMessage());
logger.error(errInterrupted.getStackTrace());
}
}
}
I read somewhere about ensuring that I need to manage resource limitations so I would have to create a maximum number of threads - arguably I could send something like 10 IPs to this class and then have the rest of the addresses 'queue' until the one has returned... I'm just not confident or fluent enough to be able to conceptualise these ideas.
EDIT: I omitted that I am restricted to Java 1.6 as this is the maximum compatible version of the JRE that we can use on this server - not sure if that hinders this effort somewhat...
Can anyone point me in the right direction?
Check ScheduledThreadPoolExecutor and ScheduledExecutorService classes in package java.util.concurrent in java API. Those and some other classes in that package would manage all resources for you. They are available in java since version 1.5
I recommend using Java's built in FTP connection platform to make a thread for continually receiving data on a specified port, until it receives a termination key.
Basically, one class will create a ServerSocket (open socket on server) and upon connection with another socket (the client socket) it would create a new thread for receiving information.
public class Server {
public ServerSocket ss;
public Socket clientSocket;
public Thread receiveingThread;
public BufferedReader inFromClient = null;
public boolean running = false;
public Server(int port) {
try {
ss = new ServerSocket(port);
startReceiving();
} catch (Exception e) {
e.printStackTrace();
}
}
public synchronized void startReceiving() {
receiveingThread = new Thread("Recieve") {
public void run() {
String dataFromClient = new String("");
while (running) {
try {
inFromClient = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
dataFromClient = inFromClient.readLine();
} catch (Exception e) {
e.printStackTrace();
}
if (dataFromClient.equals("TERMINATOR_KEY") {
stopRecieving();
}
else if(!dataFromClient.equals("")) {
//add item to array
}
}
}
};
receiveingThread.start();
}
public synchronized void stopReceiving() {
try {
running = false;
receivingThread.join();
ss.close();
clientSocket.close();
} catch (Exception e) {
e.printStackTrace();
}
System.exit(0);
}
public static void main(String[] args) {
new Server(yourPortHere);
}
}
then the client class would look something like:
public class Client {
public Socket socket;
public Thread send;
public Client(string serverPublicIP, int port) {
try {
socket = new Socket(serverPublicIP, port);
send("some IP address");
} catch (Exception e) {
e.printStackTrace();
}
}
public void send(String toSend) {
send = new Thread("Send") {
public void run() {
PrintWriter outToServer;
try {
outToServer = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));
outToServer.print(toSend);
outToServer.flush();
} catch (Exception e) {
e.printStackTrace();
}
finally {
outToServer.close();
}
}
};
send.start();
}
public static void main(String[] args) {
new Client("127.0.0.1", yourPortHere);
}
}
This is the link for the start of socket tutorials on the oracle site.
This is the Oracle Documentation for java.net.ServerSocket
This is the Oracle Documentation for java.net.Socket
I am trying to do an RMI mastermind application in java, where each client needs a separate game from the server, but somehow the combinations for each new client that runs are appended to one game, so it is as if each new client joins the main game.
Here is my server code:
public class MastermindServer
{
public static void main(String[] args) throws RemoteException, MalformedURLException
{
try
{
java.rmi.registry.LocateRegistry.createRegistry(1111);
System.out.println("RMI registry ready...");
}
catch (Exception e)
{
e.printStackTrace();
System.out.println("Exception starting RMI registry");
}
Naming.rebind("//localhost:1111/MastermindServer", new MastermindImplementation());
}
}
and my client code:
public class MastermindClient
{
private static MastermindMenuGUI menuFrame;
public static void main(String[] args)
{
System.out.println("before try catch");
try {
Registry clientRegistry = LocateRegistry.getRegistry("127.0.0.1",1111);
System.out.println("Client registry " + clientRegistry);
MastermindInterface game = (MastermindInterface) clientRegistry.lookup("theGame") ;
System.out.println("Client ready");
System.out.println(game.createCombination());
}
catch (Exception e) {
e.printStackTrace();
System.out.println("Exception in client");
}
}
}
How do I make a new separate game for each client?
Thanks in advance!
The object in the Registry should be a factory object. The client should look it up and then call a factory method which returns a new game, which should be another remote object.
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.