Pergunta

I'm working on a project for school. We are are making a harbour where you can load and unload ships. The control part is made in Netbeans and the simulation in JME. We send data from Netbeans to JME via a socket. JME is running a serversocket who is liseting to the input from Netbeans.

For example Netbeans sends an ID of a container and the crane in JME gets that container and puts it on the shore so a verhicle can pick it up.

We change a count in the main (Main.count = 2) so the SimpleUpdate can call a method. The problem is that sometimes stuff is getting skipped. Also I think it's getting worse when we send more information for instance a vehicle that's getting the container. How can I fix this? And are there other ways to get a good connection?

The code:

Netbeans

Send client

public static void run() throws Exception
{     
    Socket socket = new Socket("Localhost", 4321);      
    out = new ObjectOutputStream(socket.getOutputStream());     
}

//Sent arraystring to Simulation
public void sent(String sentString){
    try {
        out.writeObject(sentString); 
    } catch (IOException ex) {
        Logger.getLogger(CommunicationWithSimulatoin.class.getName()).log(Level.SEVERE, null, ex);
    }
}

Main send some stuff example

for(int i = Calculator.getContainersFromMaritime(); i > 1; i--)
{
    Thread.sleep(50);
    sim.sent("craneCon;" + i + ";");
    System.out.println(i);            
}

JME

Listener

public static void Listener() throws Exception {
    boolean isRunning = true;
    //Creates the server socket
    ServerSocket sSocket = new ServerSocket(4321);
    //Acception a connection from the client

    Socket socket = sSocket.accept();
    ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
    //Get the input from the client

    while (isRunning) {
        //Reads and prints the input
        test = (String) in.readObject();
        System.out.println(test);
        String[] parts = receivedString.split(";");

        if(parts[0].equals("ContainerPositionsMaritime"))
        {
            Maritime.ContainersOnBoard = receivedString.split(";");
            Main.count = 0;
        }
        if(parts[0].equals("craneCon"))
        {
            int containerId = Integer.parseInt(parts[1]);
            SeagoingCranes.idContainer = containerId;
            Main.count = 2;
        }
    }
}

Main simpleupdate

public void simpleUpdate(float tpf) {
    if(count == 0)
    {
        InitContainers();
        //martime.setLocalTranslation(0, 500.0f, 0);
        count = 999;
    }
    if(count == 2)
    {
        InitCrane(SeagoingCranes.idContainer);
        count = 999;
    }
    if(martime != null)
    {
        martime.move(0,0,0.25f*tpf);
    }
}
Foi útil?

Solução

There are a number of problems with your program.

Firstly - you have potential race and thread contention issues as you have "count" which I assume is an integer value inside the SimpleApplication is being modified from one thread and read from another. Unless the value is declared as volatile this can cause all sorts of unexpected problems and odd behaviour and even declaring it as volatile is not recommended.

Your main issue though (even leaving aside the subtle problems) is being caused by the fact that in simpleUpdate() you are scanning count and then taking an action based on count. simpleUpdate() is called once for each frame as your jME3 application is running.

If you receive more than one message in a frame then only the last one will be acted on as the count will be modified again before the next simpleUpdate() runs.

The best way to do this is to use app.enqueue().

        if(parts[0].equals("ContainerPositionsMaritime"))
        {
            final ContainersOnBoard containers = receivedString.split(";");
            mainApp.enqueue(new Callable<Spatial>() {
                public Spatial call() throws Exception {
                    mainApp.InitContainers(containers);
                    return null;
                }
            });                   
            }

        }

You can remove all the existing code from your simpleUpdate().

The Callable you enqueue will be called back from the JME3 thread in the next update and process the addition of the containers. By doing a similar thing for every different commands it will enqueue and process all the commands as the time comes. You can enqueue as many commands as you like and they will all be processed.

In general you should read up on AppStates, Controls and the threading model as they will allow you to make your code much more structured and organised.

http://hub.jmonkeyengine.org/wiki/doku.php/jme3:advanced:multithreading

http://hub.jmonkeyengine.org/wiki/doku.php/jme3:advanced:application_states

http://hub.jmonkeyengine.org/wiki/doku.php/jme3:advanced:custom_controls

P.S. You should try and follow Java style/coding conventions - for example methods should begin with lowercase. initContainers not InitContainers.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top