Search code examples
javaandroidwebsocketjettyautobahn

Autobahn Android : How to disconnect to the server


I'm using Jetty WebSockets for the server side and Autobahn Android for the client one.

A simple connection between server and client works fine. But I'm having some trouble when I try to handle the loss of connection.

On Android, what I have is this:

private void connectToServer() {

        try {

            mConnection.connect(getString(R.string.server_addr), new WebSocketHandler(){

                // connection au serveur
                @Override
                public void onOpen(){
                    Log.d(TAG, "Connected");
                    Log.d(TAG, "First connexion, sending MAC @");
                    Log.d(TAG, "My MAC Addr: "+ macAddr);
                    mConnection.sendTextMessage(macAddr);

                }
                // reception d'un message text
                @Override
                 public void onTextMessage(String payload) {

                    //TODO
                 }

                // fermeture de la connexion
                 @Override
                 public void onClose(int code, String reason) {
                    Log.d(TAG, "Connection lost. "+reason);
                    if(mConnection.isConnected()){
                        Log.d(TAG, "Still connected, disconnect!");
                        mConnection.disconnect();
                    }
                    if(code<4000){
                        int totalWaitTime = 0;
                        int waitTime = 0;
                        Log.d(TAG, "Should be disconnected");
                        while(!mConnection.isConnected()){
                            try {
                                waitTime= random.nextInt(MAX_TO_WAIT - MIN_TO_WAIT + 1) + MIN_TO_WAIT;
                                Log.d(TAG, "I'll wait "+waitTime+"ms");
                                totalWaitTime +=waitTime;
                                Log.d(TAG, "Waiting for "+totalWaitTime+"ms");
                                if(totalWaitTime <= HOUR_TO_MS){
                                    Thread.sleep(waitTime);
                                    Log.d(TAG, "Trying to reconnect");
                                    connectToServer();
                                }else{
                                    throw new InterruptedException("Attempt to connect to the server during 1 hours without success");
                                }
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                 }
            });
        } catch (WebSocketException e) {

            Log.e(TAG, "Error on connect: "+e.toString());
            Log.d(TAG, "is connected: "+mConnection.isConnected());
            if(mConnection.isConnected())
                mConnection.disconnect();
            connectToServer();
        }

    }

And I always, always have the same error:

06-26 10:36:07.823: E/wingo.stb.qos.AutoStartService(1842): Error on connect: de.tavendo.autobahn.WebSocketException: already connected

But like you can see, I close the connection in onClose(), and when a WebSocketException is catched. Does this method really works ? Or am I doing it wrong ?

By the way, mConnection is final. So maybe the problem comes here ?

private final WebSocketConnection mConnection = new WebSocketConnection();

On the server, when I have a connection loss I manually close the session:

@OnWebSocketClose
    public void onClose(Session session, int closeCode, String closeReason){
            try {
                System.out.println("connexion closed. Reason: "+closeReason);
                pingPongTimer.cancel();
                if(session.isOpen())
                    session.close();
                WebSocketsCentralisation.getInstance().leave(this);
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
    }

Thanks in advance awesome people!


Solution

  • So, what I dit was a bit messy. What I have now works:

        private void connectToServer() {
                try {
                    mConnection.connect(getString(R.string.server_addr), new WebSocketHandler(){
    
                        // connection au serveur
                        @Override
                        public void onOpen(){
                            Log.d(TAG, "Connected");
                            Log.d(TAG, "First connexion, sending MAC @");
                            Log.d(TAG, "My MAC Addr: "+ macAddr);
                            mConnection.sendTextMessage(macAddr);
    
                        }
                        // reception d'un message text
                        @Override
                         public void onTextMessage(String payload) {
    
                            //TODO
                         }
    
                        // fermeture de la connexion
                         @Override
                         public void onClose(int code, String reason) {
                            Log.d(TAG, "Connection lost. "+reason+" error code : "+code);
                            if(code<4000){
                                reconnectToServer();
                            }
                         }
                    });
                } catch (WebSocketException e) {
    
                    Log.e(TAG, "Error on connect: "+e.toString());
                    Log.d(TAG, "is connected: "+mConnection.isConnected());
                }
    
            }
    
        private void reconnectToServer() {
                try {
                    if(goConnect){
                        goConnect = false;
                        Thread.sleep(1000);
                        Log.d(TAG, "DISCONNECT:");
                        // mConnection.disconnect();
                        Log.d(TAG, "ReconnectTimer Launched");
                        new ReconnectTask().run();
                    }
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }       
                }
    
        private class ReconnectTask extends TimerTask{
            @Override
            public void run() {
                try{
                    if(totalWaitTime<HOUR_TO_MS){
                        if(!mConnection.isConnected()){
                            int waitTime= random.nextInt(MAX_TO_WAIT - MIN_TO_WAIT + 1) + MIN_TO_WAIT;
                            Log.d(TAG, "Next tentative to connect in "+waitTime+" ms");
                            totalWaitTime +=waitTime;
                            reconnectTimer.schedule(new ReconnectTask(), waitTime);
                            connectToServer();
                        }else{
                            Log.d(TAG, "Connected to the server again");
                            reinitializeReconnection();
                        }
                    }else throw new InterruptedException("Attempt to connect to the server during 1 hours without success");
                }catch(InterruptedException e){
                    Log.d(TAG, e.getMessage());
                }
    
            }
        }
    
    private void reinitializeReconnection(){
            reconnectTimer.purge();
            goConnect = true;
            totalWaitTime = 0;
        }
    

    Basically, I tried to get everything out of the WebSocketHandler. And what I didn't understand is that if you try to connect to the server in "onClose" and the server is down, it will go on "onClose" again. So I was doing recursive calls and it was really messy.