Networking woes

OK, here goes…

I’m trying to build the simplest of simple networking things: a server that communicates with clients to move around 2 players who are in the same room. Unfortunately, after 2 messages are sent, the server and client somehow automatically disconnect. I’m not sure why. I can’t tell if the problem is on the server end, or the client end, or both. I’m using the physics tutorial as a base.

I’m not using spidermonkey, just sockets and stuff. I could not find a simple spidermonkey tutorial, and would honestly rather stick to what I know.

here’s the server code:
[java]package mygame;

import com.jme3.app.SimpleApplication;
import com.jme3.asset.plugins.ZipLocator;
import com.jme3.bullet.BulletAppState;
import com.jme3.bullet.collision.shapes.CapsuleCollisionShape;
import com.jme3.bullet.collision.shapes.CollisionShape;
import com.jme3.bullet.control.CharacterControl;
import com.jme3.bullet.control.RigidBodyControl;
import com.jme3.bullet.util.CollisionShapeFactory;
import com.jme3.input.KeyInput;
import com.jme3.input.controls.ActionListener;
import com.jme3.input.controls.KeyTrigger;
import com.jme3.light.AmbientLight;
import com.jme3.light.DirectionalLight;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector2f;
import com.jme3.math.Vector3f;
import com.jme3.scene.Geometry;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
import com.jme3.scene.shape.Box;

import java.awt.event.ActionEvent;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;

import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;

/**

  • Example 9 - How to make walls and floors solid.
  • This collision code uses Physics and a custom Action Listener.
  • @author normen, with edits by Zathras
    */
    public class Main extends SimpleApplication
    implements ActionListener
    {

private Spatial sceneModel;
private BulletAppState bulletAppState;
private RigidBodyControl landscape;
private CharacterControl player;
private Vector3f walkDirection = new Vector3f();
private boolean left = false, right = false, up = false, down = false;

//Temporary vectors used on each frame.
//They here to avoid instanciating new vectors on each frame
private Vector3f camDir = new Vector3f();
private Vector3f camLeft = new Vector3f();

//client/server stuff
BufferedReader in;
PrintWriter out;

//server stats
String roomID = “F1Hall”;
String playername = “”;

public static void main(String[] args)
{
Main app = new Main();
app.start();
}

public void simpleInitApp()
{
System.out.println(“renenbo”);
try
{
//get the name of the player
playername = JOptionPane.showInputDialog(“Player Name:”);
// Make connection and initialize streams
Socket socket = new Socket(JOptionPane.showInputDialog(“IP adress:”), 9001);
in = new BufferedReader(new InputStreamReader( socket.getInputStream()));
out = new PrintWriter(socket.getOutputStream(), true);
out.println("NEW_PLAYER " + roomID + " " + playername);
}
catch(Exception e)
{
System.out.println(e);
}

/** Set up Physics */
bulletAppState = new BulletAppState();
stateManager.attach(bulletAppState);
//bulletAppState.getPhysicsSpace().enableDebug(assetManager);

// We re-use the flyby camera for rotation, while positioning is handled by physics
viewPort.setBackgroundColor(new ColorRGBA(0.7f, 0.8f, 1f, 1f));
flyCam.setMoveSpeed(100);
setUpKeys();
setUpLight();

// We load the scene from the zip file and adjust its size.
assetManager.registerLocator("town.zip", ZipLocator.class);
sceneModel = assetManager.loadModel("main.scene");
sceneModel.setLocalScale(2f);

// We set up collision detection for the scene by creating a
// compound collision shape and a static RigidBodyControl with mass zero.
CollisionShape sceneShape =
        CollisionShapeFactory.createMeshShape((Node) sceneModel);
landscape = new RigidBodyControl(sceneShape, 0);
sceneModel.addControl(landscape);

// We set up collision detection for the player by creating
// a capsule collision shape and a CharacterControl.
// The CharacterControl offers extra settings for
// size, stepheight, jumping, falling, and gravity.
// We also put the player in its starting position.
CapsuleCollisionShape capsuleShape = new CapsuleCollisionShape(1.5f, 6f, 1);
player = new CharacterControl(capsuleShape, 0.05f);
player.setJumpSpeed(20);
player.setFallSpeed(30);
player.setGravity(30);
player.setPhysicsLocation(new Vector3f(0, 10, 0));

// We attach the scene and the player to the rootnode and the physics space,
// to make them appear in the game world.
rootNode.attachChild(sceneModel);
bulletAppState.getPhysicsSpace().add(landscape);
bulletAppState.getPhysicsSpace().add(player);

}

private void setUpLight()
{
// We add light so we see the scene
AmbientLight al = new AmbientLight();
al.setColor(ColorRGBA.White.mult(1.3f));
rootNode.addLight(al);

DirectionalLight dl = new DirectionalLight();
dl.setColor(ColorRGBA.White);
dl.setDirection(new Vector3f(2.8f, -2.8f, -2.8f).normalizeLocal());
rootNode.addLight(dl);

}

/** We over-write some navigational key mappings here, so we can

  • add physics-controlled walking and jumping: */
    private void setUpKeys()
    {
    inputManager.addMapping(“Left”, new KeyTrigger(KeyInput.KEY_A));
    inputManager.addMapping(“Right”, new KeyTrigger(KeyInput.KEY_D));
    inputManager.addMapping(“Up”, new KeyTrigger(KeyInput.KEY_W));
    inputManager.addMapping(“Down”, new KeyTrigger(KeyInput.KEY_S));
    inputManager.addMapping(“Jump”, new KeyTrigger(KeyInput.KEY_SPACE));
    inputManager.addListener(this, “Left”);
    inputManager.addListener(this, “Right”);
    inputManager.addListener(this, “Up”);
    inputManager.addListener(this, “Down”);
    inputManager.addListener(this, “Jump”);
    }

/** These are our custom actions triggered by key presses.

  • We do not walk yet, we just keep track of the direction the user pressed. */
    public void onAction(String binding, boolean isPressed, float tpf)
    {
    if (binding.equals(“Left”)) {
    left = isPressed;
    } else if (binding.equals(“Right”)) {
    right= isPressed;
    } else if (binding.equals(“Up”)) {
    up = isPressed;
    } else if (binding.equals(“Down”)) {
    down = isPressed;
    } else if (binding.equals(“Jump”)) {
    if (isPressed) { player.jump(); }
    }
    }

/**

  • This is the main event loop–walking happens here.
  • We check in which direction the player is walking by interpreting
  • the camera direction forward (camDir) and to the side (camLeft).
  • The setWalkDirection() command is what lets a physics-controlled player walk.
  • We also make sure here that the camera moves with player.
    */

//set up an accumulator
int accumulator = 0;

@Override
public void simpleUpdate(float tpf)
{
accumulator++;
if(accumulator >= 3000)//
{
accumulator = 0;
try
{
out.println("MOVE_PLAYER " + roomID + " " + playername + " " + player.getPhysicsLocation());
System.out.println(out);
}
catch(Exception e)
{
System.out.println(e);
}
}

    try
    {
        if(in.ready())
        {
          String line = in.readLine();
          if(line != null && !line.equals(""))
          {
              System.out.println(line);
          }
        }
    }
    catch(Exception e)
    {
        
    }
  
  
  
  
  
  
  
  
  
  
  
  
    camDir.set(cam.getDirection()).multLocal(0.6f);
    camLeft.set(cam.getLeft()).multLocal(0.4f);
    walkDirection.set(0, 0, 0);
    if (left) {
        walkDirection.addLocal(camLeft);
    }
    if (right) {
        walkDirection.addLocal(camLeft.negate());
    }
    if (up) {
        walkDirection.addLocal(camDir);
    }
    if (down) {
        walkDirection.addLocal(camDir.negate());
    }
    player.setWalkDirection(walkDirection);
    cam.setLocation(player.getPhysicsLocation());
}

}[/java]

and the client code:

[java]import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.lang.reflect.Array;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.Scanner;
import java.util.StringTokenizer;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;

import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
public class Server
{

//create an array of printWriters
//private static ArrayList<PrintWriter> writers = new ArrayList<PrintWriter>();
private static ArrayList<Handler> handlers = new ArrayList<Handler>();
//shared stuff
//GUI
JFrame frame = new JFrame("ADMIN_ACCESS");
JTextField textField = new JTextField(40);
JTextArea messageArea = new JTextArea(8, 40);


public static void main(String[] args) throws IOException
{
	//create a server socket
	ServerSocket listener = new ServerSocket(9001);
	Server ADMIN_ACCESS = new Server();
    try
    {
        while (true)
        {
            try
            {
            	//creates a new handler and sets it to an accepted socket
            	new Handler(listener.accept()).start();
            }
            finally
            {
            	listener.close();
            }
        }
    }
    catch(Exception e)
    {
    	System.out.println("error, " + e);
    }
    finally
    {
        listener.close();
    }

}


    //constructor
    public Server()
    {

       //Gooey constructor
       //textField.setEditable(false);
       //messageArea.setEditable(false);
        frame.getContentPane().add(textField, "North");
        frame.getContentPane().add(new JScrollPane(messageArea), "Center");
        frame.pack();
        frame.setAlwaysOnTop(true);
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        // Add Listener
        textField.addActionListener(new ActionListener()
        {
           //OK, still don't get this piece.
            public void actionPerformed(ActionEvent e) 
            {
                //out.println(textField.getText());
            	for (int a = 0; a < handlers.size(); a++)//for ALL the handlers,...
                {
        			
        			handlers.get(a).printInstructions("input");//...distribute the input
                }
                textField.setText("");
            }
        });
    }



private static class Handler extends Thread
{
    private String name;
    private Socket socket;
    private BufferedReader in;
    private PrintWriter out;
    private String currentRoom = "";
    private String playername = "";
    private double x = 0;
    private double y = 0;
    private double z = 0;
    
    //creates a socket for each object
    public Handler(Socket socket)
    {
        this.socket = socket;
        handlers.add(this);
        run();
    }
    public void run()
    {
        try
        {
        	 StringTokenizer analasys; 
        	 int accumulator = 0;
        	 in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
             out = new PrintWriter(socket.getOutputStream(), true);
             //writers.add(out);
            while (true)
            {
            	if(in.ready())
                {
	            	String input = in.readLine();
	            	//System.out.println(input);
	            	System.out.println(input);
	            	if (input != null)
                    {		 
	            		//for the chat
	            		if(input.startsWith("MESSAGE:"))
	            		{
		            		for (int a = 0; a < handlers.size(); a++)//for ALL the handlers,...
		                    {
		            			
		            			handlers.get(a).printInstructions(input);//...distribute the input
		                    }
	            		}
	            		if(input.startsWith("MOVE_PLAYER"))
	            		{
	            			
	            			analasys = new StringTokenizer(input);//tokenize
	            			analasys.nextToken();//skip identifier
	            			currentRoom = analasys.nextToken();//get room number
	            			analasys.nextToken();//skip player name
	            			x = Double.parseDouble(analasys.nextToken().substring(1));//get the x value
	            			System.out.println(x);
	            			//"MOVE_PLAYER " + roomID + " " + playername + " " + player.getPhysicsLocation());
	            			for(int a = 0; a < handlers.size(); a++)//for all the handlers...
	            			{
	            				if(handlers.get(a).getCurrentRoom().equals(currentRoom))//...in the same room,...
	            				{
	            					handlers.get(a).printInstructions(input);//...redistribute the message
	            				}
	            			}
	            		}
	            		
                    }
                }        
            }
        }
        catch(Exception e)
        {
        	
        }
        finally
        {
        	handlers.remove(this);
        	try
			{
				this.socket.close();
			}
        	catch (IOException e)
			{
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
        }
    }
    
    
    
    public String getCurrentRoom()
    {
    	return currentRoom;
    }
    public void printInstructions(String message)
    {
    	out.println(message);
    	System.out.println(message);
    }
    
}

}
[/java]

I very much appreciate any help.

I wrote SpiderMonkey largely so I didn’t have to support low-level networking. It takes care of a ton of stuff you have yet to hit. There are some tutorials. There is even a fully functional TestChatClient and TestChatServer in the JME tests project. I recommend taking a look at these.

I glanced through your code and saw some empty catch() {} blocks. One of the worst coding practices because it is effectively hiding all errors from you. My guess is that some exception is happening and you don’t see it because of these. That’s as far as I got.

Others may be more willing to help on this but that’s my quick response to what was posted. Fix your try/catch stuff and maybe you will spot your errors.

1 Like

Hey, thanks for the quick response. I’m used to having to wait a week, so this is much appreciated!

Further info: I’ve done some more testing, having filled in those try-catches, and this: [java]try
{
//get the name of the player
playername = JOptionPane.showInputDialog(“Player Name:”);
// Make connection and initialize streams
Socket socket = new Socket(JOptionPane.showInputDialog(“IP adress:”), 9001);
in = new BufferedReader(new InputStreamReader( socket.getInputStream()));
out = new PrintWriter(socket.getOutputStream(), true);
out.println(“NEW_PLAYER ” + roomID + ” ” + playername);
}
catch(Exception e)
{
System.out.println(e);
}[/java]
catches an error saying the socket is closed. I never closed the socket…

@ulfgur said: Hey, thanks for the quick response. I'm used to having to wait a week, so this is much appreciated!

Further info: I’ve done some more testing, having filled in those try-catches, and this: [java]try
{
//get the name of the player
playername = JOptionPane.showInputDialog(“Player Name:”);
// Make connection and initialize streams
Socket socket = new Socket(JOptionPane.showInputDialog(“IP adress:”), 9001);
in = new BufferedReader(new InputStreamReader( socket.getInputStream()));
out = new PrintWriter(socket.getOutputStream(), true);
out.println(“NEW_PLAYER ” + roomID + ” ” + playername);
}
catch(Exception e)
{
System.out.println(e);
}[/java]
catches an error saying the socket is closed. I never closed the socket…

The other end must have.

It seems like you may not have much experience with networking and it’s really easy to get it wrong. I highly suggest using an off the shelf API for this rather than rolling your own. Whether SpiderMonkey or one of the non-JME related APIs.

Yeah, I have one weekend’s worth of experience on networking. :slight_smile: OK, if using a pre-built API will be significantly easier, I’ll bite the bullet and learn it. Could you send me a link to the tutorials you were talking about? I looked in the documentation section, but it seemed that the only page I found was built for people who kind of know what they’re doing. I either need something step-by-step or something with an example of the finished project, so that I can see how everything interacts…

The best way is probably to create a JME tests project and open the TestChatServer and TestChatClient. They do all of the types of networking.

Ooh, I didn’t know you could do that. Thanks! Hey, just a general question: (If I’m wrong about any of the following, correct me…) The documentation recommends using a simple headless server, which essentially just means that there are no associated graphics. Is there a compelling reason not to simply let one of the clients run server code? What I’m planning to do should not be a particular strain on any but the worst computers, so I don’t see the point of running the server code separately. Will I regret allowing one client to become a server/host games?

@ulfgur said: Ooh, I didn't know you could do that. Thanks! Hey, just a general question: (If I'm wrong about any of the following, correct me...) The documentation recommends using a simple headless server, which essentially just means that there are no associated graphics. Is there a compelling reason not to simply let one of the clients run server code? What I'm planning to do should not be a particular strain on any but the worst computers, so I don't see the point of running the server code separately. Will I regret allowing one client to become a server/host games?

It’s probably fine. It can just be tricky to keep one player from having an advantage.

On the other end of the spectrum, my own servers don’t even use JME Application or anything but SpiderMonkey and maybe a little com.jme3.math.

Wow, thanks. I’ll probably break something horribly in a couple minutes, so I’ll be back then…

OK, built a simple server off of the test file, it threw some exceptions that I could not make heads or tails of. Any of this worth worrying about?

Exception in thread “main” java.lang.NoClassDefFoundError: com/jme3/math/Vector3f
at com.jme3.network.serializing.Serializer.<clinit>(Serializer.java:106)
at theriseserver.TheRiseServer.initializeClasses(TheRiseServer.java:38)
at theriseserver.TheRiseServer.main(TheRiseServer.java:20)
Caused by: java.lang.ClassNotFoundException: com.jme3.math.Vector3f
at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
at java.lang.ClassLoader.loadClass(ClassLoader.java:425)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
… 3 more
Java Result: 1

java.lang.NoClassDefFoundError: com/jme3/math/Vector3f

You don’t have the JME core jar in your dependencies. SpiderMonkey requires it because it registers some default serializers.

Thanks.
fixes
The basic framework is now functional. I have a server and a client. The client transmits player location data to the server, which redistributes it.
OK, so I decided to have the server and client in separate projects so that I can run them at the same time, because I only have one computer to test this on. I want to create one library that bridges the gap between the two projects. I can make a library, add a class to it, and add it to both projects… How do I handle importing it?

If you want a library shared between two projects then the easiest way is to make a separate project and have them depend on it.

How?
I build the project, go into the other two projects and add it to the libraries, then…

@ulfgur said: How? I build the project, go into the other two projects and add it to the libraries, then...

Then what? Why would you need to do anything else? What doesn’t work? What exactly did you do? etc.

You will have to be waaaay more specific when asking for basic Netbeans support. Adding a project to project dependency is as easy as adding any other dependency.

OK, so I’m guessing I did the “making the projects depend on each other” thing right.

Once I have added a project to another’s library, how do I access that project’s classes?

I assume that an import statement is necessary. How do I build the right syntax for the import statement? does it go: import.(project name).(package name).(class name).*; where do I start?

This is a basic Java question, really. You may want to try some Java tutorials. There is nothing SDK or JME specific here.

OK, solved that, kind of. I found a way to stick everything in one package, but testing it ends with the program throwing an error. Any idea what is wrong?

error:
Mar 26, 2014 3:20:03 PM mygame.Main onAction
SEVERE: null
com.jme3.network.kernel.KernelException: Error hosting:0.0.0.0/0.0.0.0:5110
at com.jme3.network.kernel.tcp.SelectorKernel.initialize(SelectorKernel.java:97)
at com.jme3.network.base.KernelAdapter.initialize(KernelAdapter.java:100)
at com.jme3.network.base.DefaultServer.start(DefaultServer.java:157)
at mygame.Main.host(Main.java:369)
at mygame.Main.onAction(Main.java:198)
at com.jme3.input.InputManager.invokeActions(InputManager.java:169)
at com.jme3.input.InputManager.onKeyEventQueued(InputManager.java:455)
at com.jme3.input.InputManager.processQueue(InputManager.java:831)
at com.jme3.input.InputManager.update(InputManager.java:883)
at com.jme3.app.Application.update(Application.java:604)
at com.jme3.app.SimpleApplication.update(SimpleApplication.java:231)
at com.jme3.system.lwjgl.LwjglAbstractDisplay.runLoop(LwjglAbstractDisplay.java:151)
at com.jme3.system.lwjgl.LwjglDisplay.runLoop(LwjglDisplay.java:185)
at com.jme3.system.lwjgl.LwjglAbstractDisplay.run(LwjglAbstractDisplay.java:228)
at java.lang.Thread.run(Thread.java:744)
Caused by: java.net.BindException: Address already in use: bind
at sun.nio.ch.Net.bind0(Native Method)
at sun.nio.ch.Net.bind(Net.java:444)
at sun.nio.ch.Net.bind(Net.java:436)
at sun.nio.ch.ServerSocketChannelImpl.bind(ServerSocketChannelImpl.java:214)
at sun.nio.ch.ServerSocketAdaptor.bind(ServerSocketAdaptor.java:74)
at sun.nio.ch.ServerSocketAdaptor.bind(ServerSocketAdaptor.java:67)
at com.jme3.network.kernel.tcp.SelectorKernel$SelectorThread.connect(SelectorKernel.java:250)
at com.jme3.network.kernel.tcp.SelectorKernel.initialize(SelectorKernel.java:94)
… 14 more

Here’s all the code that has something to do with servers in my main class:
[java]

private void setUpKeys()
{
inputManager.addMapping(“Left”, new KeyTrigger(KeyInput.KEY_A));
inputManager.addMapping(“Right”, new KeyTrigger(KeyInput.KEY_D));
inputManager.addMapping(“Up”, new KeyTrigger(KeyInput.KEY_W));
inputManager.addMapping(“Down”, new KeyTrigger(KeyInput.KEY_S));
inputManager.addMapping(“Jump”, new KeyTrigger(KeyInput.KEY_SPACE));
inputManager.addMapping(“Host”, new KeyTrigger(KeyInput.KEY_H));
inputManager.addMapping(“Join”, new KeyTrigger(KeyInput.KEY_J));
inputManager.addListener(this, “Left”);
inputManager.addListener(this, “Right”);
inputManager.addListener(this, “Up”);
inputManager.addListener(this, “Down”);
inputManager.addListener(this, “Jump”);
inputManager.addListener(this, “Host”);
inputManager.addListener(this, “Join”);
}

/** These are our custom actions triggered by key presses.

  • We do not walk yet, we just keep track of the direction the user pressed. */
    public void onAction(String binding, boolean isPressed, float tpf)
    {
    if (binding.equals(“Left”))
    {
    left = isPressed;
    }
    else if (binding.equals(“Right”))
    {
    right= isPressed;
    }
    else if (binding.equals(“Up”))
    {
    up = isPressed;
    }
    else if (binding.equals(“Down”))
    {
    down = isPressed;
    }
    else if (binding.equals(“Host”))
    {
    try
    {
    if (isPressed)
    {
    System.out.println(“AAAAIIIGH!”);
    host();
    setUpClient();
    }
    }
    catch (Exception ex)
    {
    Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
    }
    }
    //else if (binding.equals(“Join”))
    //{
    //try
    //{
    //setUpClient();
    //isJoined = !isJoined;
    //}
    //catch (Exception ex)
    //{
    //Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
    //}
    //}
    if (binding.equals(“Jump”))
    {
    if (isPressed) { player.jump(); }
    }
    }

public void host() throws IOException, InterruptedException
{
//initializeClasses();

    // Use this to test the client/server name version check
    Server server = Network.createServer(serverInfo.NAME, serverInfo.VERSION, serverInfo.PORT, serverInfo.UDP_PORT);
    server.start();
    
    ServerHandler handler = new ServerHandler();
    server.addMessageListener(handler, ChatMessage.class);

    // ???
    synchronized(serverInfo.NAME)
    {
        serverInfo.NAME.wait();
    }

}

public static void initializeClasses()
{
//what is a serializer? something to do with networking?..
//Serializer.registerClass(mygame.ChatMessage.class);
//Serializer.registerClass(mygame.MoveMessage.class);
}

private static class ServerHandler implements MessageListener<HostedConnection>//OK, this is starting to make sense… the chat handler is a message listener, in a way…
{

    public ServerHandler()
    {
        
    }

    public void messageReceived(HostedConnection source, Message m)//if a message is received,...
    {
        if (m instanceof ChatMessage)//...and it is a chat message,...
        {
            //....assign the chat message a name,....
            source.setAttribute("name", ((ChatMessage) m).getName());
            //...alert the user to whether or not a message is reliable,...
            System.out.println("Broadcasting:" + m + "  reliable:" + m.isReliable());

            //...and rebroadcast it everywhere.
            source.getServer().broadcast(m);
        }
        else//if it is not a chat message,...
        {
            //...alert the user.
            System.err.println("Received odd message:" + m);
        }
    }
}

[/java]

I have other classes in the package. Key here is the server info package:
[java]

package mygame;

import com.jme3.network.serializing.Serializer;

public class serverInfo
{
public static final String NAME = “The Rise Server”;
public static final int VERSION = 1;
public static final int PORT = 5110;
public static final int UDP_PORT = 5110;
}

[/java]

Caused by: java.net.BindException: Address already in use

What the… Oh! What the heck? OK, I’ll see if I can fix that…