Я использую 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 основного потока.Это правильный способ поддержания состояния веб-сокета (нужен только один веб-сокет, который подключается и отключается от разных потоков)