添加服务端超时检测。由于没有心跳机制,如果服务器端断网或其他非正常断开,客户端无法感知,所以需要进行数据接收超时检测

This commit is contained in:
xinfengkun
2022-04-13 15:25:08 +08:00
parent 1635702e17
commit 07eae3389b
5 changed files with 126 additions and 93 deletions

View File

@@ -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) {

View File

@@ -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;
}
}
}

View File

@@ -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();
}
}
}
}
}
}

View File

@@ -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);

View File

@@ -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;