添加服务端超时检测。由于没有心跳机制,如果服务器端断网或其他非正常断开,客户端无法感知,所以需要进行数据接收超时检测
This commit is contained in:
@@ -131,7 +131,6 @@ public class IPCFixationIPHelper {
|
||||
}
|
||||
|
||||
private boolean ping(String str) {
|
||||
String resault;
|
||||
Process p;
|
||||
try {
|
||||
//ping -c 3 -w 100 中 ,-c 是指ping的次数 3是指ping 3次 ,-w 100 以秒为单位指定超时间隔,是指超时时间为100秒
|
||||
@@ -144,12 +143,7 @@ public class IPCFixationIPHelper {
|
||||
while ((line = in.readLine()) != null) {
|
||||
builder.append(line).append("\n");
|
||||
}
|
||||
if (status == 0) {
|
||||
resault = "是";
|
||||
} else {
|
||||
resault = "否";
|
||||
}
|
||||
builder.append("工控机IP:").append(str).append(" 是否可以连通:").append(resault);
|
||||
builder.append("工控机IP:").append(str).append(" 是否可以连通:").append(status == 0 ? "是" : "否");
|
||||
CupidLogUtils.i(TAG, builder.toString());
|
||||
return status == 0;
|
||||
} catch (IOException | InterruptedException e) {
|
||||
|
||||
@@ -0,0 +1,100 @@
|
||||
package com.zhidao.support.adas.high.common;
|
||||
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
|
||||
/**
|
||||
* 写成单例比较好控制 比如refreshLast()方法可以放到任何接收的回调中,目前放在AutopilotStateMessage 数据接口中,此接口数据刷新不是太频繁
|
||||
* 与工控机链接成功后,工控机断开连接超时监测管理器
|
||||
* 由于没有心跳机制,如果服务器端断网或其他非正常断开,客户端是无感知的,所以需要根据最后一次接收数据的时间进行超时检测
|
||||
*/
|
||||
public class ReceiveTimeoutManager {
|
||||
private static final String TAG = ReceiveTimeoutManager.class.getSimpleName();
|
||||
private static volatile ReceiveTimeoutManager INSTANCE;
|
||||
private static final long DEFAULT_TIMEOUT = 6 * 1000L;//默认超时时间
|
||||
private volatile boolean isEnable = true;//是否启用超时检测
|
||||
private volatile long lastReceiveTime;
|
||||
private OnTimeoutListener listener;
|
||||
private volatile Timer timer;
|
||||
|
||||
public interface OnTimeoutListener {
|
||||
void onTimeout(double time);
|
||||
}
|
||||
|
||||
public void setListener(OnTimeoutListener listener) {
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
private ReceiveTimeoutManager() {
|
||||
}
|
||||
|
||||
public static ReceiveTimeoutManager getInstance() {
|
||||
if (INSTANCE == null) {
|
||||
synchronized (ReceiveTimeoutManager.class) {
|
||||
if (INSTANCE == null) {
|
||||
INSTANCE = new ReceiveTimeoutManager();
|
||||
}
|
||||
}
|
||||
}
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
public boolean isEnable() {
|
||||
return isEnable;
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否启用服务器超时检测
|
||||
*
|
||||
* @param isEnable 是否启用超时检测
|
||||
* @param ipcConnectionStatus 当前连接状态
|
||||
*/
|
||||
public void setEnable(boolean isEnable, @Define.IPCConnectionStatus int ipcConnectionStatus) {
|
||||
this.isEnable = isEnable;
|
||||
//如果启动并且当前已连接
|
||||
if (isEnable) {
|
||||
if (ipcConnectionStatus == Constants.IPC_CONNECTION_STATUS.CONNECTED)
|
||||
start();
|
||||
} else {
|
||||
stop();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 刷新最后一次接收数据时间
|
||||
*/
|
||||
public void refreshLast() {
|
||||
if (isEnable)
|
||||
lastReceiveTime = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
public synchronized void start() {
|
||||
if (isEnable)
|
||||
if (timer == null) {
|
||||
refreshLast();
|
||||
timer = new Timer();
|
||||
timer.schedule(new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
long difference = System.currentTimeMillis() - lastReceiveTime;
|
||||
CupidLogUtils.e(TAG, "最后一次接收工控机数据时间与当前时间差=" + (difference / 1000.0) + "秒");
|
||||
if (difference >= DEFAULT_TIMEOUT) {
|
||||
if (listener != null) {
|
||||
listener.onTimeout(difference / 1000.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}, DEFAULT_TIMEOUT, DEFAULT_TIMEOUT);//延时
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void stop() {
|
||||
if (timer != null) {
|
||||
timer.cancel();
|
||||
timer = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,82 +0,0 @@
|
||||
package com.zhidao.support.adas.high.common;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
/**
|
||||
* 与工控机链接成功后,工控机断开连接超时监测管理器
|
||||
*/
|
||||
public class TimeoutManager {
|
||||
private static volatile TimeoutManager INSTANCE;
|
||||
private volatile long lastReceiveTime;
|
||||
private volatile Future future;
|
||||
private OnTimeoutListener listener;
|
||||
|
||||
public interface OnTimeoutListener {
|
||||
void onTimeout();
|
||||
}
|
||||
|
||||
public void setListener(OnTimeoutListener listener) {
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
private TimeoutManager() {
|
||||
}
|
||||
|
||||
public static TimeoutManager getInstance() {
|
||||
if (INSTANCE == null) {
|
||||
synchronized (TimeoutManager.class) {
|
||||
if (INSTANCE == null) {
|
||||
INSTANCE = new TimeoutManager();
|
||||
}
|
||||
}
|
||||
}
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
/**
|
||||
* 刷新最后一次接收时间
|
||||
*/
|
||||
public void refreshLase() {
|
||||
lastReceiveTime = System.currentTimeMillis();
|
||||
Log.i("Fpga", "lastReceiveTime=" + lastReceiveTime);
|
||||
}
|
||||
|
||||
public void start() {
|
||||
if (future == null) {
|
||||
future = ThreadPoolManager.getsInstance().submit(new DetectionThread());
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void stop() {
|
||||
if (future != null && !future.isCancelled()) {
|
||||
future.cancel(true);
|
||||
}
|
||||
future = null;
|
||||
}
|
||||
|
||||
private class DetectionThread implements Runnable {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
synchronized (this) {
|
||||
while (!Thread.currentThread().isInterrupted()) {
|
||||
if (System.currentTimeMillis() - lastReceiveTime > 5 * 1000L) {
|
||||
if (listener != null) {
|
||||
listener.onTimeout();
|
||||
}
|
||||
stop();
|
||||
}
|
||||
try {
|
||||
Thread.sleep(5 * 1000L);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -3,6 +3,7 @@ package com.zhidao.support.adas.high.msg;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.protobuf.InvalidProtocolBufferException;
|
||||
import com.zhidao.support.adas.high.OnAdasListener;
|
||||
import com.zhidao.support.adas.high.common.ReceiveTimeoutManager;
|
||||
|
||||
import mogo.telematics.pad.MessagePad;
|
||||
|
||||
@@ -17,6 +18,7 @@ public class AutopilotStateMessage extends MyAbstractMessageHandler {
|
||||
|
||||
@Override
|
||||
public void handlerMsg(MessagePad.Header header, byte[] msg, OnAdasListener adasListener) throws InvalidProtocolBufferException {
|
||||
ReceiveTimeoutManager.getInstance().refreshLast();
|
||||
MessagePad.AutopilotState autopilotState = MessagePad.AutopilotState.parseFrom(msg);
|
||||
if (adasListener != null) {
|
||||
adasListener.onAutopilotState(header, autopilotState);
|
||||
|
||||
@@ -15,6 +15,7 @@ import androidx.annotation.NonNull;
|
||||
import com.google.protobuf.InvalidProtocolBufferException;
|
||||
import com.zhidao.support.adas.high.AdasChannel;
|
||||
import com.zhidao.support.adas.high.common.CupidLogUtils;
|
||||
import com.zhidao.support.adas.high.common.ReceiveTimeoutManager;
|
||||
import com.zhidao.support.adas.high.queue.WSByteQueueManager;
|
||||
import com.zhidao.support.adas.high.queue.WebSocketQueueManager;
|
||||
import com.zhjt.service.chain.ChainLog;
|
||||
@@ -65,7 +66,11 @@ public class FpgaSocket implements IWebSocket {
|
||||
/**
|
||||
* 是否启用自动重连
|
||||
*/
|
||||
private volatile boolean isReconnect = true;
|
||||
private boolean isReconnect = true;
|
||||
/**
|
||||
* 接收数据超时原因 null时表示不是接收数据超时的原因
|
||||
*/
|
||||
private volatile String receiveTimeoutReason = null;
|
||||
|
||||
public FpgaSocket() {
|
||||
init();
|
||||
@@ -79,7 +84,14 @@ public class FpgaSocket implements IWebSocket {
|
||||
okBuilder = new OkHttpClient.Builder();
|
||||
okBuilder.writeTimeout(4, TimeUnit.SECONDS)
|
||||
.readTimeout(4, TimeUnit.SECONDS)
|
||||
.connectTimeout(1, TimeUnit.SECONDS);
|
||||
.connectTimeout(2, TimeUnit.SECONDS);
|
||||
ReceiveTimeoutManager.getInstance().setListener(new ReceiveTimeoutManager.OnTimeoutListener() {
|
||||
@Override
|
||||
public void onTimeout(double time) {
|
||||
receiveTimeoutReason = "已超过" + time + "秒未收到工控机数据,将要进行重连";
|
||||
onClose(receiveTimeoutReason);
|
||||
}
|
||||
});
|
||||
}
|
||||
if (client == null) {
|
||||
client = okBuilder.build();
|
||||
@@ -113,7 +125,6 @@ public class FpgaSocket implements IWebSocket {
|
||||
* 重连
|
||||
*/
|
||||
public void reconnect() {
|
||||
CupidLogUtils.i(TAG, "WebSocket 是否启用自动重连=" + isReconnect);
|
||||
if (isReconnect) {
|
||||
if (!isUserCloseWebSocket) {
|
||||
try {
|
||||
@@ -207,6 +218,7 @@ public class FpgaSocket implements IWebSocket {
|
||||
if (!isConnect) {
|
||||
reconnect();
|
||||
} else {
|
||||
ReceiveTimeoutManager.getInstance().start();
|
||||
CupidLogUtils.i(TAG, "WebSocket 连接成功");
|
||||
if (mWebSocketConnectListener != null)
|
||||
mWebSocketConnectListener.onWebSocketConnectSuccess(ipAddress, port);
|
||||
@@ -277,10 +289,16 @@ public class FpgaSocket implements IWebSocket {
|
||||
public void onFailure(@NonNull WebSocket webSocket, @NonNull Throwable t, Response response) {
|
||||
super.onFailure(webSocket, t, response);
|
||||
CupidLogUtils.e(TAG, "WebSocket onFailure= " + t);
|
||||
t.printStackTrace();
|
||||
String reason = t.toString();
|
||||
//连接异常或关闭异常不进行堆栈打印
|
||||
if (!reason.toLowerCase().contains("failed to connect to") && !reason.contains("Socket closed"))
|
||||
t.printStackTrace();
|
||||
if (TextUtils.isEmpty(reason))
|
||||
reason = "onFailure";
|
||||
if (!TextUtils.isEmpty(receiveTimeoutReason)) {
|
||||
reason = receiveTimeoutReason;
|
||||
receiveTimeoutReason = null;
|
||||
}
|
||||
if (mWebSocket != null) {
|
||||
close(false, 1001);
|
||||
}
|
||||
@@ -289,6 +307,7 @@ public class FpgaSocket implements IWebSocket {
|
||||
}
|
||||
|
||||
private void onConnectFailed(String reason) {
|
||||
ReceiveTimeoutManager.getInstance().stop();
|
||||
if (mWebSocketConnectListener != null) {
|
||||
if (isUserCloseWebSocket)
|
||||
reason = null;
|
||||
|
||||
Reference in New Issue
Block a user