Skip to main content
GameDev.net gamedev.net
🔒 Locked

Java UDP Multicast problems with sending data

Started by Canvas Mar 2, 2013 at 3:20 PM 5 replies 5.5k views
Original Post
Canvas
Canvas

Hey guys,

I'm working on a Pong network game, I have it working using TCP/IP fine, but I can't seem to send data from the client to the server using UDP.

Here is my server I created


package Pong;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.MulticastSocket;
import java.net.Socket;

//This is the actual server
public class PongUDPServerThread extends Thread {
	
	//speed to send data
	private long dataSpeed = 10;
	private int port = 4447;
	private int idPlayer = 0;
	private PongModel model;
	private PongView  view;
	private PongPlayerThread players[] = new PongPlayerThread[2];
	private MulticastSocket socket = null;
	private InetAddress group;
	private int ID = 1;
	
	public PongUDPServerThread() throws IOException 
	{
		super("PongUDPServerThread");
	}
	
	public String rtnInfo()
	{
		String str;
		str = model.getBall().getX() + ":" +
			  model.getBall().getY() + ":" +
			  model.getBats()[0].getX() + ":" +
			  model.getBats()[0].getY() + ":" +
			  model.getBats()[1].getX() + ":" +
			  model.getBats()[1].getY();
		return str;
	}
	
	public void setupPong() throws IOException 
	{
		System.out.println("Pong");
		model = new PongModel();
		view  = new PongView();
		        new PongController( model, view );

		model.addObserver( view );       // Add observer to the model

		//view.setVisible(true);           // Display Screen
		model.makeActiveObject();        // Start play
		//start server
		socket = new MulticastSocket(port);
		InetAddress group = InetAddress.getByName("230.0.0.1");
		socket.joinGroup(group);
		//socket.setReuseAddress(true);
		//Inform server user
		System.out.println("Server is running");
	}
	
	public void run()
	{
		//Server loop
		while(true)
		{
			
			//Receive data
			byte[] recBuf = new byte[256];
			DatagramPacket recData = new DatagramPacket(recBuf, recBuf.length);
			try
			{
			socket.receive(recData);
			}
			catch (IOException e)
			{
				e.printStackTrace();
			}
			try
			{
				byte[] buf = new byte[256];
				
				//Gather data
				buf = rtnInfo().getBytes();
				//System.out.println(buf.toString());
				
				//Send data
				DatagramPacket packet = new DatagramPacket(buf, buf.length, InetAddress.getByName("230.0.0.1"), port);
				socket.send(packet);
				
				//Sleep the server
				try
				{
					sleep((long)dataSpeed);
				}
				catch (InterruptedException e)
				{
					
				}
			}
			catch (IOException e)
			{
				e.printStackTrace();
			}
		}
		
		//socket.close();
		
	}
	
}

And here is my client


package Pong;

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

public class PongUDPClient {
	
	private static int port = 4447;

	public static void main(String[] args) throws IOException
	{
		
		//Setup pong rdy
		PongModel model = new PongModel();
	    PongView  view  = new PongView();
	                      new PongController( model, view );

	    model.addObserver( view );       // Add observer to the model
	    
	    String pos;
	    
	    model.makeActiveObject();        // Start play
	    //model.clientModel();
		
		MulticastSocket socket = new MulticastSocket(port);
		//socket.setReuseAddress(true);
		InetAddress address = InetAddress.getByName("230.0.0.1");
		//Join the UDP list port
		socket.joinGroup(address);
		
		DatagramPacket packet;
		view.setVisible(true);           // Display Screen
		
		System.out.println("Connected");
		//Id is sent here.
		
		while(true)
		{
			
			//Lets try to send some data to the server
			byte[] sendData = new byte[256];
			String data = "Hello";
			sendData = data.getBytes();
			DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, InetAddress.getByName("230.0.0.1"), port);
			socket.send(sendPacket);
			
			byte[] buf = new byte[256];
			packet = new DatagramPacket(buf, buf.length);
			socket.receive(packet);
			//Sending data
			/*byte[] sendBuf = new byte[256];
    		String data = "up";
			sendBuf = data.getBytes();
			DatagramPacket sendPacket = new DatagramPacket(sendBuf, sendBuf.length, InetAddress.getByName("230.0.0.1"), port);
    		socket.send(sendPacket);*/
			
			String  received = new String(packet.getData(), 0, packet.getLength());
			//System.out.println("Server data: " + received);
			
			String[] posValues = received.split(":");

	    	model.getBall().setX(Double.parseDouble(posValues[0]));
	    	model.getBall().setY(Double.parseDouble(posValues[1]));
	    	model.getBats()[0].setX(Double.parseDouble(posValues[2]));
	    	model.getBats()[0].setY(Double.parseDouble(posValues[3]));
	    	model.getBats()[1].setX(Double.parseDouble(posValues[4]));
	    	model.getBats()[1].setY(Double.parseDouble(posValues[5]));
	    	
	    	//Check for keyboard input
	    	
	    	if(PongController.moveUp == true && PongController.moveDown == false)
	    	{
	    		System.out.println("Up");
	    		PongController.moveUp = false;
	    	}
	    	else if(PongController.moveUp == false && PongController.moveDown == true)
	    	{
	    		System.out.println("Down");
	    		PongController.moveDown = false;
	    	}
	    	else
	    	{
	    		//serverOut.println("nothing");
	    	}
			
		}
	}

}

When I start my server, and then connect a client, the client will receive one package from the server then stop and throw this error in console


Exception in thread "main" java.lang.NumberFormatException: For input string: "Hello"
	at sun.misc.FloatingDecimal.readJavaFormatString(Unknown Source)
	at java.lang.Double.parseDouble(Unknown Source)
	at Pong.PongUDPClient.main(PongUDPClient.java:63)

Line 63 is me just trying to use the data from the server I receive.

If anyone could shine some light on this or help me out at all, it would be great :)

Canvas

Bruno Sofiato
Bruno Sofiato

I guess the client is receiving the same datagram that itself has sent.

hplus0603
hplus0603

The server and client run on the same IP and same port, but I'm sure that is not the problem

When multiple processes use the same port number on the same host, then only one of them will get any particular incoming datagram. This may be great for scaling a single-threaded program across many cores (fork many processes and have them all bind to the same port) but it's certainly not good for your client/server game situation.

The client should not have to bind to any particular port number. Just let the UDP implementation assign a port number the first time you call sendto().
enum Bool { True, False, FileNotFound };
Bruno Sofiato
Bruno Sofiato

I know it sound strange, but try this :


public static void main(String[] args) throws Exception {
    MulticastSocket x = new MulticastSocket(45607);
    x.joinGroup(InetAddress.getByName("230.0.0.1"));
    String data = "SENT MESSAGE";
    DatagramPacket packetToBeSent = new DatagramPacket(data.getBytes(), data.length(), InetAddress.getByName("230.0.0.1"), 45607);
    x.send(packetToBeSent);
    DatagramPacket packetReceived = new DatagramPacket(new byte [256], 256);
    x.receive(packetReceived);
    System.out.println(new String(packetReceived.getData()));
  }

And see what just got printed wink.png

Canvas
Canvas

so Hplus which line would that be?



packet = new DatagramPacket(receiveBuf, receiveBuf.length, InetAddress.getByName("230.0.0.1"), port);

and remove the InetAddress and port?

Doing this comes up with this error


Exception in thread "main" java.lang.NullPointerException: null address || null buffer
	at java.net.PlainDatagramSocketImpl.send(Native Method)
	at java.net.DatagramSocket.send(Unknown Source)
	at Pong.PongUDPClient.main(PongUDPClient.java:53)

or

MulticastSocket socket = new MulticastSocket(port);

Doing this the client doesn't even receive any data from the server

and just remove the port number?

------------------

Can I not just get rid of Multicast socket and just use a DatagramSocket instead? All i want is data from the server to be sent to clients connected, and clients can sent data back, Multicast seems to only allow data to be sent, and DatagramSocket seems to allow data to be sent and received

hplus0603
hplus0603
Multicast only works if all routers between you and the client are configured to support the particular multicast groups you're using.
The problem with this is that, to "actually work," every router on the internet would need to be aware of every multicast group in the world to be able to join new clients to it. That... doesn't scale ;-)
If you are working on a local LAN/VLAN, you may be able to get multicast to work. It can provide some savings in very specific situations (local simulations, data centers, etc.)
An alternative is to use broadcast, which also only works on a LAN, but doesn't usually need router assistance.
If you are working on the greater internet, the only way you can make this work is to build unicast "connections" by keeping a table of who has connected to the server in the server (remote ip:port pair) and you send your broadcasts to each of those ip:port pairs in turn. You probably want to time out a remote ip:port pair after a little while if you haven't heard back from them, to avoid sending packets into the Aether forever...
enum Bool { True, False, FileNotFound };

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.