I am creating a custom 2d turn based game engine in Java, and so far everything works great. Currently, I have come to the dreaded networking :), and I made a test code, prototype of the network that I would like to create. It uses Java's MulticaseSocket class, DatagramPackets and UDP (obviously). I chose to go with this because it is turn based, so there is no need for direct connection to a server, instead it is more like everyone talking to everyone, with ONE person broadcasting their movements, attacks and such, and everyone else listening. My problem here is, that my serializable class, VarnaPacket, is sent but not recieved on the other end. If I replace the sending code to sen a string, it recieves it, but it does not recieve my serializable object. Can someone PLEASE help!?

VarnaNetwork.java

package Network;

import java.io.*;
import java.net.*;

import Statics.EngineOptions;

public class VarnaNetwork extends Thread{
	
	boolean gameRunning = true;
	boolean myTurn = false;
	MulticastSocket socket;
	InetAddress address;
	
	public VarnaNetwork() throws IOException {
		socket = new MulticastSocket(EngineOptions.PORT_NUM);
    	address = InetAddress.getByName(VarnaNetworkDataStructure.SERVER_ADDRESS);
		socket.joinGroup(address);
    }
	
	public void run()
	{
		try
		{
			socket = new MulticastSocket(EngineOptions.PORT_NUM);
	    	address = InetAddress.getByName(VarnaNetworkDataStructure.SERVER_ADDRESS);
			socket.joinGroup(address);
			
	    	if(VarnaNetworkDataStructure.PLAYER_ID == 1)
	    	{
	    		myTurn = true;
	    	}
	    	else
	    	{
	    		recv();
	    	}
		}
		catch (Exception e)
		{
			
		}
	}
	
	public void send(int player)
	{
		try
		{
			if(myTurn)
			{
				if(player != VarnaNetworkDataStructure.PLAYER_ID)
				{
					System.out.println("my turn is over!");
					myTurn = false;
				}
				
				/*ByteArrayOutputStream b_out = new ByteArrayOutputStream();
				ObjectOutputStream o_out = new ObjectOutputStream(b_out);

				o_out.writeObject("" + new VarnaPacket(player));*/
				
				ByteArrayOutputStream baos = new ByteArrayOutputStream();
				ObjectOutputStream oos = new ObjectOutputStream(baos);
				oos.writeObject("" + new VarnaPacket(player));
				byte[] b= baos.toByteArray();

				//byte[] b = b_out.toByteArray();

		
				//byte[] buf = new byte[256];
		        
		        /*String dString = System.console().readLine("Input: ");
		        buf = dString.getBytes();
		        
		        if(VarnaNetworkDataStructure.PLAYER_ID != VarnaNetworkDataStructure.TOTAL_PLAYERS)
		        {
		            if(dString.compareTo("start " + (VarnaNetworkDataStructure.PLAYER_ID + 1)) == 0)
		            {
		            	System.out.println("My turn is over!");
		            	myTurn = false;
		            }
		        }
		        else
		        {
		        	if(dString.compareTo("start " + 1) == 0)
		            {
		            	System.out.println("My turn is over!");
		            	myTurn = false;
		            }
		        }*/
				//System.out.println("Sending data..!");
					        
		        InetAddress group = InetAddress.getByName(VarnaNetworkDataStructure.SERVER_ADDRESS);
		        DatagramPacket packet = new DatagramPacket(b, b.length, group, EngineOptions.PORT_NUM);
		        socket.send(packet);
			}
		}
		catch(Exception e)
		{
			
		}
	}

	public void recv()
	{
		while(!myTurn)
		{
			try
			{
				socket = new MulticastSocket(EngineOptions.PORT_NUM);
		        address = InetAddress.getByName(VarnaNetworkDataStructure.SERVER_ADDRESS);
				socket.joinGroup(address);
			
			    DatagramPacket packet;
			    
			    byte[] buf = new byte[65535];
			    
			    
		        packet = new DatagramPacket(buf, buf.length);
		        System.out.println("Trying to recieve");
		        socket.receive(packet);
		        System.out.println("Gotchya");
		        
		        ByteArrayInputStream b_in = new ByteArrayInputStream(packet.getData());
		        ObjectInputStream o_in = new ObjectInputStream(b_in);
		        VarnaPacket p = (VarnaPacket) o_in.readObject();
		        System.out.println("player turn is:" + p.getTurn());
		        /*if(p.getTurn() == VarnaNetworkDataStructure.PLAYER_ID)
		        {
		        	myTurn = true;
		        	System.out.println("HOORAY its my turn!");
		        }
		        else
		        {
		        	System.out.println(p.getTurn());
		        }*/
		        
		        /*String received = new String(packet.getData(), 0, packet.getLength());
		        System.out.println("Quote of the Moment: " + received);
		        
		        if(received.compareTo("start " + VarnaNetworkDataStructure.PLAYER_ID) == 0)
		        {
		        	System.out.println("My turn is starting!");
		        	myTurn = true;
		        }*/
				}
			catch (Exception e)
			{
				
			}
		}
	}
	/*public void run() {
		while(gameRunning){
			try{
				if(!myTurn)
				{
					socket = new MulticastSocket(EngineOptions.PORT_NUM);
			        address = InetAddress.getByName(VarnaNetworkDataStructure.SERVER_ADDRESS);
					socket.joinGroup(address);
				
				    DatagramPacket packet;
				    
				    byte[] buf = new byte[65535];
				    ByteArrayInputStream b_in = new ByteArrayInputStream(buf);
				    
		            packet = new DatagramPacket(buf, buf.length);
		            socket.receive(packet);
		            
		            ObjectInputStream o_in = new ObjectInputStream(b_in);
		            VarnaPacket o = (VarnaPacket) o_in.readObject();
		            b_in.reset(); // reset so next read is from start of byte[] again
		            
		            if(vpacket.PLAYER_TURN == VarnaNetworkDataStructure.PLAYER_ID)
		            {
		            	myTurn = true;
		            	System.out.println("HOORAY its my turn!");
		            }
		            
		            String received = new String(packet.getData(), 0, packet.getLength());
		            System.out.println("Quote of the Moment: " + received);
		            
		            if(received.compareTo("start " + VarnaNetworkDataStructure.PLAYER_ID) == 0)
		            {
		            	System.out.println("My turn is starting!");
		            	myTurn = true;
		            }
				}
				else
				{
					ByteArrayOutputStream b_out = new ByteArrayOutputStream();
					ObjectOutputStream o_out = new ObjectOutputStream(b_out);

					o_out.writeObject(vpacket);

					byte[] b = b_out.toByteArray();

					//byte[] buf = new byte[256];
	                
	                String dString = System.console().readLine("Input: ");
	                buf = dString.getBytes();
	                
	                if(VarnaNetworkDataStructure.PLAYER_ID != VarnaNetworkDataStructure.TOTAL_PLAYERS)
	                {
		                if(dString.compareTo("start " + (VarnaNetworkDataStructure.PLAYER_ID + 1)) == 0)
		                {
		                	System.out.println("My turn is over!");
		                	myTurn = false;
		                }
	                }
	                else
	                {
	                	if(dString.compareTo("start " + 1) == 0)
		                {
		                	System.out.println("My turn is over!");
		                	myTurn = false;
		                }
	                }
					//System.out.println("Sending data..!");
					if(vpacket.PLAYER_TURN != VarnaNetworkDataStructure.PLAYER_ID)
					{
						myTurn = false;
					}
	                
	                InetAddress group = InetAddress.getByName(VarnaNetworkDataStructure.SERVER_ADDRESS);
	                DatagramPacket packet = new DatagramPacket(b, b.length, group, EngineOptions.PORT_NUM);
	                socket.send(packet);
				}
			}catch (IOException e) {
                e.printStackTrace();
                gameRunning = false;
            } catch (ClassNotFoundException e) {
				e.printStackTrace();
			}
		}
		
		try {
			socket.leaveGroup(address);
		} catch (IOException e) {
			e.printStackTrace();
		}
		socket.close();
    }
    
    public static byte[] getBytes(Object obj) throws java.io.IOException{
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bos);
        oos.writeObject(obj);
        oos.flush();
        oos.close();
        bos.close();
        byte [] data = bos.toByteArray();
        return data;
    }*/

}

VarnaPacket.java

package Network;

import java.io.Serializable;
import java.util.Vector;

import Unit.Unit;
import World.Building;

public class VarnaPacket implements Serializable{
	private static final long serialVersionUID = 4970897833545316377L;
	private Vector<Unit>[] units;
	private Vector<Building> buildings;
	
	private int PLAYER_TURN;
	
	public VarnaPacket(int turn)
	{
		PLAYER_TURN = turn;
		units = VarnaNetworkDataStructure.units;
		buildings = VarnaNetworkDataStructure.buildings;
	}
	
	public int getTurn()
	{
		return PLAYER_TURN;
	}
}

If anyone can help me make this network and fix this dilemna of sending a serializble object, I would gladly appreciate. Oh, also please do not suggest an RMI, It is easier, but I really want efficiency rather than easiness (is that even a word? Oh well you know what I mean :D) Thank You!

Recommended Answers

All 8 Replies

> oos.writeObject("" + new VarnaPacket(player));

This line means you are sending across a string object and not a VernaPacket object hence the cast on the receiving end fails.

Even if I remove that ""+, it makes it worse and it doesn't even get to the "gotchya" output(cheezy I know), so when I add the ""+ , it at least gets to the gotchya, do you have any better solutions?

Have you tried a small test program to work out the details on this technique? Something you could post here for others to work with.

yes, I actually have :D. I called it MulticastClient I believe. It is one file, and it takes 2 arguments in the console, the first argument being the ID of the client, and the second being the total number of clients. So you can invoke one instance of the class sending 1 and 3, then 2 and 3, then 3 and 3. It does what I need it to, except with strings. If you want the next client to start sending, you have to type start 2, start 3 or start 1.

import java.io.*;
import java.net.*;

public class MulticastClient{
	boolean gameRunning = true;
	boolean myTurn = false;
	MulticastSocket socket;
	InetAddress address;
	
	int myNum;
	int numPlayers;
	
	public MulticastClient(String args[]) throws IOException {
    	socket = new MulticastSocket(4446);
    	address = InetAddress.getByName("230.0.0.1");
		socket.joinGroup(address);
		
		myNum = Integer.valueOf(args[0]);
    	numPlayers = Integer.valueOf(args[1]);
    	
    	if(myNum == 1)
    	{
    		myTurn = true;
    	}
		
		run();
    }
	
	public void run() {
		while(gameRunning){
			try{
				if(!myTurn)
				{
					socket = new MulticastSocket(4446);
			        address = InetAddress.getByName("230.0.0.1");
					socket.joinGroup(address);
				
				    DatagramPacket packet;
				    
				    byte[] buf = new byte[256];
		            packet = new DatagramPacket(buf, buf.length);
		            socket.receive(packet);
		
		            String received = new String(packet.getData(), 0, packet.getLength());
		            System.out.println("Quote of the Moment: " + received);
		            
		            if(received.compareTo("start " + myNum) == 0)
		            {
		            	System.out.println("My turn is starting!");
		            	myTurn = true;
		            }
				}
				else
				{
					byte[] buf = new byte[256];
	                
	                String dString = System.console().readLine("Input: ");
	                buf = dString.getBytes();
	                
	                if(myNum != numPlayers)
	                {
		                if(dString.compareTo("start " + (myNum + 1)) == 0)
		                {
		                	System.out.println("My turn is over!");
		                	myTurn = false;
		                }
	                }
	                else
	                {
	                	if(dString.compareTo("start " + 1) == 0)
		                {
		                	System.out.println("My turn is over!");
		                	myTurn = false;
		                }
	                }
	                
	                InetAddress group = InetAddress.getByName("230.0.0.1");
	                DatagramPacket packet = new DatagramPacket(buf, buf.length, group, 4446);
	                socket.send(packet);
				}
			}catch (IOException e) {
                e.printStackTrace();
                gameRunning = false;
            }
		}
		
		try {
			socket.leaveGroup(address);
		} catch (IOException e) {
			e.printStackTrace();
		}
		socket.close();
    }

    public static void main(String[] args) throws IOException {
    	new MulticastClient(args);
    }
    
    public static byte[] getBytes(Object obj) throws java.io.IOException{
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bos);
        oos.writeObject(obj);
        oos.flush();
        oos.close();
        bos.close();
        byte [] data = bos.toByteArray();
        return data;
    }

}

So, you just have to create a bat file and send those 2 arguments to each instance, and when you have say 2 clients, the first one automatically gets rights to broadcast, type "start 2", and client 2 will now get the turn to broadcast and client 1 starts listening :). Thank You!

yes, I actually have :D. I called it MulticastClient I believe. It is one file, and it takes 2 arguments in the console, the first argument being the ID of the client, and the second being the total number of clients. So you can invoke one instance of the class sending 1 and 3, then 2 and 3, then 3 and 3. It does what I need it to, except with strings. If you want the next client to start sending, you have to type start 2, start 3 or start 1.

import java.io.*;
import java.net.*;

public class MulticastClient{
	boolean gameRunning = true;
	boolean myTurn = false;
	MulticastSocket socket;
	InetAddress address;
	
	int myNum;
	int numPlayers;
	
	public MulticastClient(String args[]) throws IOException {
    	socket = new MulticastSocket(4446);
    	address = InetAddress.getByName("230.0.0.1");
		socket.joinGroup(address);
		
		myNum = Integer.valueOf(args[0]);
    	numPlayers = Integer.valueOf(args[1]);
    	
    	if(myNum == 1)
    	{
    		myTurn = true;
    	}
		
		run();
    }
	
	public void run() {
		while(gameRunning){
			try{
				if(!myTurn)
				{
					socket = new MulticastSocket(4446);
			        address = InetAddress.getByName("230.0.0.1");
					socket.joinGroup(address);
				
				    DatagramPacket packet;
				    
				    byte[] buf = new byte[256];
		            packet = new DatagramPacket(buf, buf.length);
		            socket.receive(packet);
		
		            String received = new String(packet.getData(), 0, packet.getLength());
		            System.out.println("Quote of the Moment: " + received);
		            
		            if(received.compareTo("start " + myNum) == 0)
		            {
		            	System.out.println("My turn is starting!");
		            	myTurn = true;
		            }
				}
				else
				{
					byte[] buf = new byte[256];
	                
	                String dString = System.console().readLine("Input: ");
	                buf = dString.getBytes();
	                
	                if(myNum != numPlayers)
	                {
		                if(dString.compareTo("start " + (myNum + 1)) == 0)
		                {
		                	System.out.println("My turn is over!");
		                	myTurn = false;
		                }
	                }
	                else
	                {
	                	if(dString.compareTo("start " + 1) == 0)
		                {
		                	System.out.println("My turn is over!");
		                	myTurn = false;
		                }
	                }
	                
	                InetAddress group = InetAddress.getByName("230.0.0.1");
	                DatagramPacket packet = new DatagramPacket(buf, buf.length, group, 4446);
	                socket.send(packet);
				}
			}catch (IOException e) {
                e.printStackTrace();
                gameRunning = false;
            }
		}
		
		try {
			socket.leaveGroup(address);
		} catch (IOException e) {
			e.printStackTrace();
		}
		socket.close();
    }

    public static void main(String[] args) throws IOException {
    	new MulticastClient(args);
    }
    
    public static byte[] getBytes(Object obj) throws java.io.IOException{
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bos);
        oos.writeObject(obj);
        oos.flush();
        oos.close();
        bos.close();
        byte [] data = bos.toByteArray();
        return data;
    }

}

So, you just have to create a bat file and send those 2 arguments to each instance, and when you have say 2 clients, the first one automatically gets rights to broadcast, type "start 2", and client 2 will now get the turn to broadcast and client 1 starts listening :). Thank You!

Your test version is too complicated and tedious to work with.
Can you make what I have here work and show the problem. See the comment: "Here there needs ..."

/*
yes, I actually have . I called it MulticastClient I believe. It is one file, and it takes 2 arguments in the console, 
the first argument being the ID of the client, and the second being the total number of clients. So you can invoke one
instance of the class sending 1 and 3, then 2 and 3, then 3 and 3. It does what I need it to, except with strings. 
If you want the next client to start sending, you have to type start 2, start 3 or start 1.

So, you just have to create a bat file and send those 2 arguments to each instance, and when you have say 2 clients, 
the first one automatically gets rights to broadcast, type "start 2", and client 2 will now get the turn to broadcast
and client 1 starts listening . Thank You!

 */
import java.io.*;
import java.net.*;

public class MulticastClient implements Runnable {
	boolean gameRunning = true;
	boolean myTurn = false;
	MulticastSocket socket;
	InetAddress address;
	
	int myNum;
	int numPlayers;
	
	public MulticastClient(String args[]) throws IOException {
      System.out.println("Starting " + args[0]);
    	socket = new MulticastSocket(4446);
    	address = InetAddress.getByName("230.0.0.1");
		socket.joinGroup(address);
		
		myNum = Integer.parseInt(args[0]);
    	numPlayers = Integer.parseInt(args[1]);
    	
    	if(myNum == 1)    	{
    		myTurn = true;
    	}
		
//		run();
      Thread t = new Thread(this);  // start the run() method on its own thread
      t.start();
    }
	
    //---------------------------------------------------------
	public void run() {
		while(gameRunning){
			try{
				if(!myTurn)
				{
					socket = new MulticastSocket(4446);
			        address = InetAddress.getByName("230.0.0.1");
					socket.joinGroup(address);
				
				    DatagramPacket packet;
				    
				    byte[] buf = new byte[256];
		            packet = new DatagramPacket(buf, buf.length);
		            socket.receive(packet);
		
		            String received = new String(packet.getData(), 0, packet.getLength());
		            System.out.println(myNum + " Quote of the Moment: " + received);
		            
		            if(received.compareTo("start " + myNum) == 0)
		            {
		            	System.out.println("My turn is starting!");
		            	myTurn = true;
		            }
				}
				else
				{
					byte[] buf = new byte[256];
	                // Here there needs to be some logic to decide what to enter
	                String dString = "start 1"; //System.console().readLine("Input: ");
	                buf = dString.getBytes();
	                
	                if(myNum != numPlayers)
	                {
		                if(dString.compareTo("start " + (myNum + 1)) == 0)
		                {
		                	System.out.println("My turn is over!");
		                	myTurn = false;
		                }
	                }
	                else
	                {
	                	if(dString.compareTo("start " + 1) == 0)
		                {
		                	System.out.println("My turn is over!");
		                	myTurn = false;
		                }
	                }
	                
	                InetAddress group = InetAddress.getByName("230.0.0.1");
	                DatagramPacket packet = new DatagramPacket(buf, buf.length, group, 4446);
	                socket.send(packet);
				}
			}catch (IOException e) {
                e.printStackTrace();
                gameRunning = false;
            }
		} // end while()
		
		try {
			socket.leaveGroup(address);
		} catch (IOException e) {
			e.printStackTrace();
		}
		socket.close();
    } // end run()

    //--------------------------------------------------------------
    public static void main(String[] args) throws IOException {
        // Start three clients with their args
    	new MulticastClient(new String[]{"1", "3"});
    	new MulticastClient(new String[]{"2", "3"});
    	new MulticastClient(new String[]{"3", "3"});
    }
    
    //---------------------------------------------------------------------
    public static byte[] getBytes(Object obj) throws java.io.IOException{
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bos);
        oos.writeObject(obj);
        oos.flush();
        oos.close();
        bos.close();
        byte [] data = bos.toByteArray();
        return data;
    }

}

Hey sorry about the long reply, a lot of physics homework and labs and test :). Either ways I am testing it right now, give me a couple of minutes I will edit this post if it works or not :D

Alright, so I tested it implemented it and after a couple of days of bugging, I found what is wrong in my OWN code. If I remove the unit and building vectors, it sent properly. After some more research and debugging, I found out that the ONE un-serializable object in both classes was java.awt.Image . I now know why the objects were not sent, because one of the objects in either class is unserializable. Can someone please provide me a method to serialize this image QUICKLY? I tried this:

private void getBuilding(Image image)
	{
		Image img = toolkit.createImage(new FilteredImageSource(image.getSource(),
                                new CropImageFilter(sheet_x, sheet_y,
                                EngineOptions.TILE_DIMENSION, EngineOptions.TILE_DIMENSION)));
		
		int[] pixels = new int[EngineOptions.TILE_DIMENSION * EngineOptions.TILE_DIMENSION];
		PixelGrabber pg = new PixelGrabber(img, 0, 0, EngineOptions.TILE_DIMENSION,
				EngineOptions.TILE_DIMENSION, pixels, 0, EngineOptions.TILE_DIMENSION);
		try {
			pg.grabPixels();
			building = new MemoryImageSource(EngineOptions.TILE_DIMENSION, EngineOptions.TILE_DIMENSION, pixels,
					0, EngineOptions.TILE_DIMENSION);
		} catch (InterruptedException e) {}
	}
	
	public Image getImage() {
		return toolkit.createImage(building);
	}

I try and store the iamge in the last possible serializable state, which I think is a MemoryImageSource. On running though, the canvas displays the image properly, but it constantly flickers. What to do?

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.