Okhttp WebSocket отключается и не может подключиться в течение длительного времени - PullRequest
0 голосов
/ 02 марта 2019

Я использую okhttp 3.13.1, у меня есть три разных потока, которые вызывают мой класс WebSocketClient с одноэлементным экземпляром и синхронизируются

public static WebSocketClient getInstance() {
    if (sINSTANCE == null) {
        synchronized (LOCK) {
            if (sINSTANCE == null) {
                sINSTANCE = new WebSocketClient();
            }
            return sINSTANCE;
        }
    }
    return sINSTANCE;
}

Он будет подключаться и работать должным образом в течение некоторого периода времени.После этого будет вызвано сообщение об ошибке, и потребуется около 5-10 минут для повторного подключения.

Если я отключу соединение вручную, оно подключится в течение 1-2 секунд

public boolean connect(String ip_address, final String pending_data) {
    final String url = WEBSOCKET_TAG + ip_address + ":" + DEFAULT_WEBSOCKET_PORT;
    SimpleDateFormat dateFormat = new SimpleDateFormat("hh.mm.ss a");
    String currentTime = dateFormat.format(new Date());
    Log.d("Time", "[Connect called at]--> " + currentTime);
    //check if we need to turn it on or not
    if (mPendingConnection.compareAndSet(NO_PENDING_CONNECTION, true) && !mIsConnected.get()) {
        Log.d(TAG + "11", "connection request started");
        try {
            //2.Build request with the desired IP address of the Server
            mRequest = new Request.Builder()
                    .url(url)
                    .build();
        } catch (Exception e) {
            //3. if Request got Failed then set all states to false and return false
            UpdateConnectionStatus(false);
            Log.d(TAG, "connect: error creating request please check ip_address" + e.getMessage());
            return false;
        }
        try {
            //4. Create Client passing the request to create a webSocket connection
            mClient = MyStateManager.getmWebSocketClient();
            mWebSocket = mClient.newWebSocket(mRequest, new WebSocketListener() {
                /**
                 * Called when the Connection is established
                 * @param webSocket
                 * @param response
                 */
                @Override
                public void onOpen(WebSocket webSocket, Response response) {
                    Log.d(TAG + "11", "ON OPEN CALLED");
                    UpdateConnectionStatus(true);
                    SimpleDateFormat dateFormat = new SimpleDateFormat("hh.mm.ss a");
                    String currentTime = dateFormat.format(new Date());
                    Log.d("Time", "[ connection established at] --> " + currentTime);
                    Log.d(TAG, "onOpen: connection established ");
                    Log.d(TAG, "threadsignature onopen" + Helper.getThreadSignature());

                    if (pending_data != null) {
                        //send any pending data on connect
                        webSocket.send(pending_data);
                    }

                }

                /***
                 * All messages are received here : String type
                 * @param webSocket
                 * @param text receives Text data over the socket connection
                 */
                @Override
                public void onMessage(WebSocket webSocket, String text) {
                    UpdateConnectionStatus(true);
                    if (text != null) {
                        Log.d("onMessage", "onMessage: Received-->" + text);
                        System.out.println("MESSAGE Received: " + text);

                        Log.d(TAG, "time after msg received   " + System.currentTimeMillis());
                    }
                }

                @Override
                public void onMessage(WebSocket webSocket, String text) {
                    UpdateConnectionStatus(true);
                    if (text != null) {

                        Log.d("onMessage", "onMessage: Received-->" + text);
                        System.out.println("MESSAGE Received: " + text);

                        Log.d(TAG, "box time after msg received   " + System.currentTimeMillis());
                    }
                }
                /**
                 * Called when we manually call close websocket
                 * @param webSocket
                 * @param code
                 * @param reason
                 */
                @Override
                public void onClosing(WebSocket webSocket, int code, String reason) {
                    UpdateConnectionStatus(false);
                    webSocket.close(CLOSURE_STATUS, null);
                    Log.d(TAG, "onClosing: websocket closing ");
                    if (reason != null) {
                    Log.d(TAG, "reason: "+reason);
        }}
                @Override
                public void onClosed(WebSocket webSocket, int code, String reason) {
                    UpdateConnectionStatus(false);
                    Log.d(TAG, "Websocket Closed");
                    if (reason != null) {
                        super.onClosed(webSocket, code, reason);
                    }
                }
                @Override
                public void onFailure(WebSocket webSocket, Throwable t, Response response) {
                    Log.d(TAG + "11", "ON FAILURE CALLED");
                    UpdateConnectionStatus(false);
                    if (t != null) {
                        Log.d(TAG, " Exception Type = " + t.getClass());
                        Log.d(TAG, "[webSocket onFailure:] " + t.getMessage());

                        SimpleDateFormat dateFormat = new SimpleDateFormat("hh.mm.ss a");
                        String currentTime = dateFormat.format(new Date());
                        Log.d("Time", "[ onFailure called at ] --> " + currentTime);
                    }

                    //1.if The we retry to connect more then 3 times and it comes in failure then we send http request to server
                    Log.d(TAG, "[onFailure called retry count]-->" + mRetryCountFailure);

                    if (mRetryCountFailure > 3) {
                        Log.d(TAG, "[onFailure called more then 3 times-->sending request ");
                        mRetryCountFailure = RESET_RETRY_COUNT;//retry count for the failure
                        sendPingRequestForConnectionCheck();
                    }

                    //2.disconnect the socket
                    disconnect();
                    //3.try reconnect the socket
                    reconnectSocket();

                }
            });
        } catch (Exception e) {
            //5 . if connection breaks due to anything then update the states and return false
            UpdateConnectionStatus(false);
            Log.d(TAG, "connect: connection faliure" + e.getMessage());
            return false;
        }

    } else {
        //6. we check if any new connection request is there or not
        Log.d(TAG + "22", "Connection request already in progress so we ignore a new connect request");
        if (isConnected()) {

        }
        if (sPendingConnectionCount.getValue() > MAX_PENDING_REQUESTS) {
            sPendingConnectionCount = new AtomicCounter(-1);
            //restart all the states
            mPendingConnection.set(false);
            Log.d(TAG + "22", "Max PENDING connection request reached-->something is wrong");
        } else {
            sPendingConnectionCount.increment();
            Log.d(TAG + "22", "current pending request = " + sPendingConnectionCount.getValue());
        }
        return false;
    }


    return true;
}

мой метод повторного подключения

 public void reconnectSocket() {
    mRetryCountFailure++;
    SimpleDateFormat dateFormat = new SimpleDateFormat("hh.mm.ss a");
    String currentTime = dateFormat.format(new Date());
    Log.d("Time", "[ reconnect called at ] --> " + currentTime);
    Handler handler = new Handler(Looper.getMainLooper());

    //1.before recconnecting checking that socket is null so that we can make new connection
    if (!this.isConnected()) {
        handler.postDelayed(new Runnable() {
            public void run() {
                Log.d(TAG, "threadsignature reconnect run" + Helper.getThreadSignature());
                if (isConnected()) {

                } else {
                    connectFromSharedPrefs(null);                       
                }
            }
        }, CommonDataApplication.getInstance().getResources().getInteger(R.integer.websocket_reconnect_time));
    }
}

мой метод отключения

public void disconnect() {
    if (mWebSocket != null) {
        if (isConnected()) {
            mClient.connectionPool().evictAll();
            mWebSocket.close(CLOSURE_STATUS, "bye");

            SimpleDateFormat dateFormat = new SimpleDateFormat("hh.mm.ss a");
            String currentTime = dateFormat.format(new Date());
            Log.d("Time", "disconnect: at--> " + currentTime);


            //Clear the connection pool
            UpdateConnectionStatus(false);
        }
    }
}

Иногда я сталкиваюсь с повторным подключением, которое занимает 5-10 минут.Я звоню через websocket сообщение о подключении из 3 разных потоков, 2 фоновых и 1 основного потока.Это правильный способ поддержания состояния веб-сокета (нужен только один веб-сокет, который подключается и отключается от разных потоков)

...