Why do my client crashes on sending message? (Termining connection due to unhandled error)

Going through documentation, i made a simple server and client. Both runs, server sees connection. But sending message crashes client.



LOG:

[xml]SEVERE: Client started

авг 15, 2012 1:25:20 AM com.jme3.network.base.DefaultClient handleError

SEVERE: Termining connection due to unhandled error

com.jme3.network.kernel.ConnectorException: Connector closed.

at com.jme3.network.base.ConnectorAdapter.run(ConnectorAdapter.java:162)



авг 15, 2012 1:25:20 AM com.jme3.app.Application handleError

SEVERE: Uncaught exception thrown in Thread[LWJGL Renderer Thread,5,main]

java.lang.IllegalStateException: Client is not started.

at com.jme3.network.base.DefaultClient.checkRunning(DefaultClient.java:119)

at com.jme3.network.base.DefaultClient.send(DefaultClient.java:223)

at com.jme3.network.base.DefaultClient.send(DefaultClient.java:208)

at mygame.Main$1.onAnalog(Main.java:95)

at com.jme3.input.InputManager.invokeAnalogs(InputManager.java:244)

at com.jme3.input.InputManager.invokeUpdateActions(InputManager.java:214)

at com.jme3.input.InputManager.update(InputManager.java:852)

at com.jme3.app.Application.update(Application.java:598)

at com.jme3.app.SimpleApplication.update(SimpleApplication.java:233)

at com.jme3.system.lwjgl.LwjglAbstractDisplay.runLoop(LwjglAbstractDisplay.java:149)

at com.jme3.system.lwjgl.LwjglDisplay.runLoop(LwjglDisplay.java:182)

at com.jme3.system.lwjgl.LwjglAbstractDisplay.run(LwjglAbstractDisplay.java:223)

at java.lang.Thread.run(Thread.java:722)



BUILD SUCCESSFUL (total time: 5 seconds)

[/xml]



CODE:

[java]package mygame;



import com.jme3.app.SimpleApplication;

import com.jme3.input.KeyInput;

import com.jme3.input.controls.KeyTrigger;

import com.jme3.input.controls.AnalogListener;

import com.jme3.material.Material;

import com.jme3.math.ColorRGBA;

import com.jme3.math.Vector3f;

import com.jme3.network.Client;

import com.jme3.network.Network;

import com.jme3.renderer.RenderManager;

import com.jme3.network.serializing.Serializable;

import com.jme3.network.AbstractMessage;

import com.jme3.network.Message;

import com.jme3.network.serializing.Serializer;

import com.jme3.scene.Geometry;

import com.jme3.scene.shape.Box;

import java.io.IOException;

import java.util.logging.Level;

import java.util.logging.Logger;





/**

  • test
  • @author normenhansen

    /

    public class Main extends SimpleApplication {



    protected Geometry player1;

    protected Geometry player2;

    protected Client myClient;

    public static void main(String[] args) {

    Main app = new Main();

    app.start();

    }



    @Override

    public void simpleInitApp() {

    Logger.getLogger("").setLevel(Level.WARNING);

    try {

    myClient = Network.connectToServer("localhost", 6143);

    myClient.start();

    myClient.addMessageListener(new ClientListener(), PosUpd.class);

    Logger.getLogger(SCR_Server.class.getName()).log(Level.SEVERE, "Client started");

    } catch (IOException ex) {

    Logger.getLogger(Main.class.getName()).log(Level.SEVERE, "Cannot run client", ex);

    }



    Box b = new Box(Vector3f.ZERO, 1, 1, 1);

    player1 = new Geometry("Box", b);

    player2 = new Geometry("Box", b);



    Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");

    mat.setColor("Color", ColorRGBA.Blue);

    Material mat2 = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");

    mat2.setColor("Color", ColorRGBA.Red);



    player1.setMaterial(mat);

    player2.setMaterial(mat2);



    rootNode.attachChild(player1);

    rootNode.attachChild(player2);



    player2.setLocalTranslation(0, 2, 0);

    cam.setLocation(new Vector3f(0f,0f,60f));

    flyCam.setEnabled(false);

    initKeys();

    Serializer.registerClass(PosUpd.class);



    }



    private void initKeys() {

    // You can map one or several inputs to one named action

    inputManager.addMapping("Left", new KeyTrigger(KeyInput.KEY_LEFT));

    inputManager.addMapping("Right", new KeyTrigger(KeyInput.KEY_RIGHT));

    inputManager.addMapping("Space", new KeyTrigger(KeyInput.KEY_SPACE));

    // Add the names to the action listener.

    inputManager.addListener(analogListener, new String[]{"Left", "Right", "Space"});



    }

    private AnalogListener analogListener = new AnalogListener() {

    public void onAnalog(String name, float value, float tpf) {

    if (name.equals("Right")) {

    Vector3f v = player1.getLocalTranslation();

    player1.setLocalTranslation(v.x + value
    speed4, v.y, v.z);

    }

    if (name.equals("Left")) {

    Vector3f v = player1.getLocalTranslation();

    player1.setLocalTranslation(v.x - value
    speed*4, v.y, v.z);

    }

    if (name.equals("Space")) {

    float p1_transform = player1.getLocalTranslation().x;

    Message message = new PosUpd(p1_transform);

    myClient.send(message);

    }

    }

    };



    @Serializable

    public static class PosUpd extends AbstractMessage {

    private float player_pos; // custom message data

    public PosUpd() {} // empty constructor

    public PosUpd(float s) { player_pos = s; } // custom constructor

    }



    @Override

    public void simpleUpdate(float tpf) {



    }



    @Override

    public void simpleRender(RenderManager rm) {

    //TODO: add render code

    }

    }

    [/java]

The client isn’t started yet. Its running on another thread so you have to check if its ready.

@normen said:
The client isn’t started yet. Its running on another thread so you have to check if its ready.

But I bound message sending to key press. I can wait minute or two, and it still crashes, after I pressing space.

Oh I see the connection is closed. Any firewalls running?

Windows XP Firewall and avast antivirus. Just tried with both disabled. Same thing.

This line is a thorn in my eye:



[java]Message message = new PosUpd(p1_transform);[/java]

(line 94 in your code)

try



[java]PosUpd message = new PosUpd(p1_transform);[/java]



instead

I see a lot of problems though not necessarily the cause of this one.



First, you should register all of your listeners before you start the Client otherwise if the server sends you something then you will miss it and get a warning.



Second, you should register your serialized classes before you start the Client (before even creating the client connection is best) otherwise if the server sends you something then you will get an error.



So the way you have it is almost exactly backwards.

Also, client and server both need exactly the same classes registered in exactly the same order. Exactly.



Put it in static method on a utility class that is shared by both client and server so that you can always be sure they are the same.

Thank you all for replies. Wish I could find more time to play with JME.