Files
CUTV_FileSystemV2/src/main/java/cn/minoa/dataRequestInterface/MinoaDataAPI.java
T
2020-08-21 22:13:22 +08:00

775 lines
33 KiB
Java

package cn.minoa.dataRequestInterface;
// 与服务器进行数据交互
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import cn.minoa.model.SingleNotice;
import cn.minoa.util.Aes;
import cn.minoa.util.KeyStorageUtil;
import net.named_data.jndn.*;
import net.named_data.jndn.security.pib.Pib;
import net.named_data.jndn.security.pib.PibImpl;
import net.named_data.jndn.security.tpm.Tpm;
import net.named_data.jndn.security.tpm.TpmBackEnd;
import net.named_data.jndn.security.v2.CertificateV2;
import org.json.JSONException;
import org.json.JSONObject;
import cn.minoa.MainApp;
import cn.minoa.model.SingleMessage;
import net.named_data.jndn.encoding.EncodingException;
import net.named_data.jndn.security.KeyChain;
import net.named_data.jndn.security.SecurityException;
import net.named_data.jndn.security.pib.PibIdentity;
import net.named_data.jndn.security.pib.PibImpl.Error;
import net.named_data.jndn.security.pib.PibSqlite3;
import net.named_data.jndn.security.tpm.TpmBackEndMemory;
import net.named_data.jndn.util.Blob;
public class MinoaDataAPI {
public static String keyChainNameString = "/default";
public static String minoaServerIpString;
public static Integer minoaServerPortInteger;
public static String globalPrefixString;
// private String pidDbPathString;
// 同一兴趣包超时或丢包次数达到上限时的错误信息
public static String timeoutError = "timeout times reaches the upper limit.";
// 由于连接问题(多次超时/丢包),返回给主线程的错误码
public static Integer timeoutCodeInteger = 333;
// 同一兴趣包超时或丢包次数达到上限时的错误信息
public static String nackError = "receive nack.";
// 由于连接问题(多次超时/丢包),返回给主线程的错误码
public static Integer nackCodeInteger = 334;
// 除文件上下传外的应答codeInteger非200/201时的报错信息
// 判断是否是200/201,不会导致界面卡死,超时才会
public static String wrongAnswerError = "answer codeInteger is not 200/201.";
// public static KeyChain keyChain;
public static Face face;
public volatile DataCacheQueue dataCacheQueue;
private MainApp mainApp;
// 标志连接是否正常
private boolean isConnected;
//发送的数据是否发送成功,key:第几个数据片,从0开始,value:该数据片超时次数
private Map<Long, Integer> timeOutNums = new ConcurrentHashMap<>();
// 超时重传上限数值,某个兴趣包的重传次数超过此数值,则放弃重传,直接返回false
private Integer timeoutCeil = 10;
public MinoaDataAPI(MainApp mainApp) {
// TODO Auto-generated constructor stub
minoaServerIpString = mainApp.minoaServerIpString;
minoaServerPortInteger = mainApp.minoaServerPortInteger;
globalPrefixString = mainApp.globalPrefixString;
isConnected = false;
this.dataCacheQueue = new DataCacheQueue();
this.mainApp = mainApp;
// pidDbPathString=mainApp.getClientPath()+ File.separator+"ndn";
// System.out.println("pidDbPathString: "+pidDbPathString);
runFace(minoaServerIpString, minoaServerPortInteger);
// 首先按照"/default"初始化KeyChain
try {
KeyManager.INSTANCE.initKeyChain(keyChainNameString);
} catch (Pib.Error | PibImpl.Error | Tpm.Error | TpmBackEnd.Error | CertificateV2.Error | KeyChain.Error error) {
error.printStackTrace();
}
// 从本地初始化keyName
String keyString=KeyStorageUtil.getKeyName();
try {
// 如果本地keyName指向的证书确实在keyChain中,就将该证书取出
if((keyString!=null)&&(KeyManager.INSTANCE.isInKeyChain(keyString))){
keyChainNameString=keyString;
System.out.println("keyChainNameString: "+keyChainNameString);
// 再次按照本地证书前缀初始化KeyChain
try {
KeyManager.INSTANCE.initKeyChain(keyChainNameString);
} catch (Pib.Error | Error | Tpm.Error | TpmBackEnd.Error | CertificateV2.Error | KeyChain.Error error) {
error.printStackTrace();
}
}
} catch (Pib.Error | PibImpl.Error | Tpm.Error | TpmBackEnd.Error | CertificateV2.Error | KeyChain.Error error) {
error.printStackTrace();
}
// try {
// // 密钥“黑盒”
// PibSqlite3 pibSqlite3 = new PibSqlite3(pidDbPathString);
// TpmBackEndMemory tpmBackEndMemory = new TpmBackEndMemory();
// keyChain = new KeyChain(pibSqlite3, tpmBackEndMemory);
// PibIdentity identity = keyChain.getPib().getIdentity(new Name(keyChainNameString));
// keyChain.setDefaultIdentity(identity);
//
// System.out.println(keyChain.getDefaultCertificateName().toUri());
// } catch (Exception e) {
// // TODO: handle exception
// System.out.println("exception: " + e.getMessage());
// }
}
/**
* 判断某个key对应的兴趣包的超时次数是否超过阈值
*
* @return
*/
private boolean isInterestTimeOut(Long timeoutMapKey) {
if (timeOutNums.get(timeoutMapKey) > timeoutCeil) {
return true;
}
return false;
}
// 开辟线程运行face
public boolean runFace(String ipString, Integer portInteger) {
if (isConnected) {
return true;
}
this.face = new Face(ipString, portInteger);
isConnected = true;
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
// System.out.println("face is trying to link...");
// TODO Auto-generated method stub
try {
while (true) {
face.processEvents();
// 线程暂时休眠
Thread.sleep(5);
}
} catch (InterruptedException | EncodingException | IOException e) {
// TODO Auto-generated catch block
// e.printStackTrace();
System.out.println(e.getMessage());
isConnected = false;
}
}
});
thread.start();
return isConnected;
}
public boolean runFace(String ipString) {
return this.runFace(ipString, minoaServerPortInteger);
}
public boolean runFace() {
return this.runFace(minoaServerIpString, minoaServerPortInteger);
}
// 开辟线程监听新消息/新通知/新审批:作为心跳包存在,五秒一次
public void bindNews() {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
while (true) {
// 监听是否有新消息等,有,则将其加载到数据内存
bindNewsProdution();
// 线程暂时休眠
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
});
thread.start();
}
// 监听函数:作为心跳包存在,不进行任何处理
public void bindNewsProdution() {
// 发送数据请求
Long seqLong = mainApp.getNewDataReqId();
OrderInfo orderInfo = new OrderInfo();
orderInfo.setSeq(seqLong);
orderInfo.setJsonString(getGetNewsJson());
mainApp.minoaDataAPI.executeOrder("/getNews", orderInfo);
// 获取回复消息
ResponseData responseData = mainApp.minoaDataAPI.dataCacheQueue.getResponseDataBySeq(seqLong);
// System.out.println("getNews-responseData: "+responseData.getResponseJsonDataString());
JSONObject jsonObject = responseData.praseRequestData();
Integer codeInteger = null;
try {
codeInteger = jsonObject.getInt("code");
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(jsonObject.toString());
// 如果需要查看登录状态且登录失效
if (mainApp.isNeedKnowLoginStatus&&(codeInteger == 407)) {
// 登录失效
mainApp.isNeedKnowLoginStatus=false;
mainApp.reLogin();
}
// String dataString;
// try {
// dataString = jsonObject.getString("data");
// if (!dataString.equals("")) {
//// System.out.println("getNews-responseData: "+responseData.getResponseJsonDataString());
// JSONArray dataJsonArray = new JSONArray(dataString);
// String newsCacheString;
// JSONObject newsCacheJsonObject;
// Integer typeCodeInteger;
// String contentString;
// // 遍历每个新消息或者通知或者审批 将其更新到前端内存数据中
// for (int i = 0; i < dataJsonArray.length(); i++) {
// newsCacheString = dataJsonArray.getString(i);
// newsCacheJsonObject = new JSONObject(newsCacheString);
// typeCodeInteger = newsCacheJsonObject.getInt("typeCode");
// contentString = newsCacheJsonObject.getString("content");
// if (typeCodeInteger == 0) {
// // 处理新消息
// handleNewSingleMessage(contentString);
// } else if (typeCodeInteger == 1) {
// // 处理新通知
//// System.out.println("getNews-responseData: "+responseData.getResponseJsonDataString());
// handleNewSingleNotice(contentString);
// } else if (typeCodeInteger == 2) {
// // 处理新审批[报销审批、邮件]
// System.out.println("getNews-responseData: "+responseData.getResponseJsonDataString());
// handleNewSingleApproval(contentString);
// }
// }
// }else{
//// System.out.println("getNews-responseData: "+responseData.getResponseJsonDataString());
// }
// } catch (JSONException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// }
// }
}
//接收到一个新的审批[邮件/报销审批等,除掉通知]
private void handleNewSingleApproval(String singleApprovalString) {
try {
JSONObject singleApprovalJsonObject = new JSONObject(singleApprovalString);
//拿到审批类型
Integer typeCodeInteger = singleApprovalJsonObject.getInt("typeCode");
if (typeCodeInteger == 2) {
System.out.println("接收到一条新的报销审批【我是审核人】");
mainApp.handleGetNewReimToSelf();
} else if (typeCodeInteger == 3) {
System.out.println("接收到一条新的邮件【我是接收方】");
mainApp.handleGetNewEmailToSelf();
}
} catch (JSONException e) {
e.printStackTrace();
}
}
//接收到一个新的通知
private void handleNewSingleNotice(String singleNoticeString) {
String singleNoticeCacheString = singleNoticeString;
JSONObject singleNoticeCacheJsonObject;
Integer noticeIdInteger;
String usernameCacheString;
String titleCacheString;
String contentCacheString;
String starttimeCacheString;
String endtimeCacheString;
String attachementCacheString;
try {
singleNoticeCacheJsonObject = new JSONObject(singleNoticeCacheString);
//拿到通知ID
noticeIdInteger = singleNoticeCacheJsonObject.getInt("approvalId");
// 拿到新闻发布人
usernameCacheString = singleNoticeCacheJsonObject.getString("proposer");
// 拿到content
// JSONObject detailJsonObject = singleNoticeCacheJsonObject.getJSONObject("detail");
String detailString = singleNoticeCacheJsonObject.getString("detail");
System.out.println("通知详细: " + detailString);
JSONObject detailJsonObject = new JSONObject(detailString);
contentCacheString = detailJsonObject.getString("content");
// 拿到title
titleCacheString = detailJsonObject.getString("title");
// 拿到starttime、endtime
starttimeCacheString = detailJsonObject.getString("startTime");
endtimeCacheString = detailJsonObject.getString("endTime");
// 拿到attachment
attachementCacheString = detailJsonObject.getString("attachment");
// System.out.println("user-"+i+": "+usernameCacheString);
// 新建一个notice
SingleNotice singleNotice = new SingleNotice();
singleNotice.setNoticeId(noticeIdInteger);
singleNotice.setContent(contentCacheString);
singleNotice.setUsername(usernameCacheString);
singleNotice.setTitle(titleCacheString);
singleNotice.setStarttime(starttimeCacheString);
singleNotice.setEndtime(endtimeCacheString);
singleNotice.setAttachment(attachementCacheString);
//判断该通知是否已经渲染到前端
boolean flagInNoticeList = isInNoticeList(singleNotice.getNoticeId());
if (!flagInNoticeList) {
mainApp.handleGetNewNotice(singleNotice);
System.out.println("MinoaDataAPI-handleGetNewMessage success: " + singleNoticeString);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
//判断某个通知(的ID)是否已经在前端数据中存在
boolean isInNoticeList(Integer noticeId) {
boolean flag = false;
for (int i = 0; i < mainApp.noticeList.size(); i++) {
if (mainApp.noticeList.get(i).getNoticeId() == noticeId) {
flag = true;
break;
}
}
return flag;
}
// 获取是否有新的[消息/通知/审批]产生的json字符串
private String getGetNewsJson() {
JSONObject jsonObject = new JSONObject();
String commandString = "/getNews";
String userNameString = mainApp.loginer.getUserName();
String uuidString = mainApp.loginer.getUuid();
try {
jsonObject.put("command", commandString);
jsonObject.put("username", userNameString);
jsonObject.put("uuid", uuidString);
} catch (Exception e) {
// TODO: handle exception
System.out.println("exception: " + e.getMessage());
}
return jsonObject.toString();
}
// 处理一条接收到的新聊天消息
private void handleNewSingleMessage(String singleMessageString) {
try {
JSONObject singleMessageJsonObject = new JSONObject(singleMessageString);
String fromString;
JSONObject fromJsonObject;
String fromNameString;
Integer idInteger;
String msgString;
Long timeLong;
// 解析发送方姓名
fromString = singleMessageJsonObject.getString("from");
fromJsonObject = new JSONObject(fromString);
fromNameString = fromJsonObject.getString("username");
// 解析id
idInteger = singleMessageJsonObject.getInt("id");
// 解析内容
msgString = singleMessageJsonObject.getString("msg");
// 解析时间
timeLong = singleMessageJsonObject.getLong("time");
// 构建一条消息对象
SingleMessage singleMessage = new SingleMessage();
singleMessage.setFromName(fromNameString);
singleMessage.setMsg(msgString);
singleMessage.setTime(timeLong);
singleMessage.setToName(mainApp.loginer.getUserName());
singleMessage.setMsgId(idInteger);
// 将这条新消息交给mainApp处理
mainApp.handleGetNewMessage(singleMessage);
System.out.println("MinoaDataAPI-handleGetNewMessage success: " + singleMessageString);
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
// 根据命令前缀获取相应的请求字符串【JSON】
public static String getRequestStr(String orderPrefix, OrderInfo orderInfo) {
String requestStr;
switch (orderPrefix) {
case "/register":
requestStr = orderInfo.getJsonString();
break;
case "/login":
requestStr = orderInfo.getJsonString();
break;
case "/getUsers":
requestStr = orderInfo.getJsonString();
break;
case "/sendRTMsg":
requestStr = orderInfo.getJsonString();
break;
case "/getRTMsg":
requestStr = orderInfo.getJsonString();
break;
case "/getRTMsgLog":
requestStr = orderInfo.getJsonString();
break;
case "/getInform":
requestStr = orderInfo.getJsonString();
break;
case "/hasNews":
requestStr = orderInfo.getJsonString();
break;
case "/getNews":
requestStr = orderInfo.getJsonString();
break;
case "/fileAction":
requestStr = orderInfo.getJsonString();
break;
case "/fileInfo":
requestStr = orderInfo.getJsonString();
break;
case "/fileShareInfo":
requestStr = orderInfo.getJsonString();
break;
case "/downloadFile":
requestStr = orderInfo.getJsonString();
break;
case "/downloadShareFile":
requestStr = orderInfo.getJsonString();
break;
case "/uploadFile":
requestStr = orderInfo.getJsonString();
break;
case "/sendApproval":
requestStr = orderInfo.getJsonString();
break;
case "/getApproval":
requestStr = orderInfo.getJsonString();
break;
case "/getDataSlice":
requestStr = orderInfo.getJsonString();
break;
case "/dealApproval":
requestStr = orderInfo.getJsonString();
break;
case "/ecos_begin":
requestStr = orderInfo.getJsonString();
break;
case "/ecos_end":
requestStr = orderInfo.getJsonString();
break;
default:
requestStr = "*wrong command string*";
break;
}
return requestStr;
}
// 执行数据请求语句
public boolean executeOrder(String orderPrefix, OrderInfo orderInfo) {
// 获取json格式的数据请求字符串
String requestStr = getRequestStr(orderPrefix, orderInfo);
System.out.println("requestStr: "+requestStr);
// 命令前缀格式不对的情况下返回false
if (requestStr.equals("*wrong command string*")) {
System.out.println(requestStr);
return false;
}
// AES加密
byte[] requestByte=null;
if(orderPrefix.equals("/register")||orderPrefix.equals("/login")){
}else{
try {
requestByte= Aes.newEncrypt(requestStr,Aes.getDefaultKey());
// requestStr=Aes.Encrypt(requestStr);
} catch (Exception e) {
System.out.println("AES加密错误:"+e.getMessage());
}
}
// 发送数据兴趣包
Name name = new Name(globalPrefixString + orderPrefix+"/"+orderInfo.getSeq()
+"/" +mainApp.loginer.getUserName()+"/"+(System.currentTimeMillis()/1000+MainApp.timeStampBias));
Interest interest = new Interest(name);
interest.setMustBeFresh(true);
// if(orderPrefix.equals("/login")){
if(orderPrefix.equals("/register")||orderPrefix.equals("/login")){
Base64.Decoder base64Decoder = Base64.getMimeDecoder() ;
interest.setApplicationParameters(new Blob(base64Decoder.decode(requestStr)));
}else{
interest.setApplicationParameters(new Blob(requestByte));
}
interest.setInterestLifetimeMilliseconds(2000);
try {
// keyChain.sign(interest);
// 使用KeyManager管理兴趣包签名
KeyManager.INSTANCE.getKeyChain().sign(interest);
this.expressTheInterest(orderPrefix, interest, orderInfo.getSeq());
return true;
} catch (Exception e) {
System.out.println("exception: " + e.getMessage());
return false;
}
}
// 提供特殊接口,执行数据请求语句:为ECOS信号服务
public boolean executeOrder(String orderPrefix,Interest interest,Long seq) {
try {
this.expressTheInterest(orderPrefix, interest, seq);
return true;
} catch (Exception e) {
System.out.println("exception: " + e.getMessage());
return false;
}
}
// 提供特殊接口,执行时间戳同步语句
public boolean executeOrder(String orderPrefix,OrderInfo orderInfo,boolean isTimeSync) {
// 发送数据兴趣包
Name name = new Name(globalPrefixString + orderPrefix+"/"+orderInfo.getSeq());
Interest interest = new Interest(name);
interest.setMustBeFresh(true);
System.out.println("time sync: "+orderInfo.getJsonString());
interest.setApplicationParameters(new Blob(orderInfo.getJsonString()));
interest.setInterestLifetimeMilliseconds(2000);
try {
// keyChain.sign(interest);
// 使用KeyManager管理兴趣包签名
KeyManager.INSTANCE.getKeyChain().sign(interest);
this.expressTheInterest(orderPrefix, interest, orderInfo.getSeq());
return true;
} catch (Exception e) {
System.out.println("exception: " + e.getMessage());
return false;
}
}
private void expressTheInterest(String orderPrefix, Interest interest, Long dataReqId) {
ResponseData responseData = new ResponseData();
responseData.setPrefix(orderPrefix);
HandleInterestTimeOutAndNack handleInterestTimeOutAndNack =
new HandleInterestTimeOutAndNack(orderPrefix, interest, dataReqId);
try {
// 使用匿名内部类,发送数据请求兴趣包
if (orderPrefix.equals("/getDataSlice")) {
//接收数据块
face.expressInterest(interest, new OnData() {
@Override
public void onData(Interest interest, Data data) {
// int contentSize = data.getContent().size();
// System.out.println("该大数据传输的数据块分片长度为:" + contentSize);
// byte[] content = new byte[contentSize];
// for (int i = 0; i < contentSize; i++) {
// content[i] = data.getContent().buf().get(i);
// System.out.print(i + ": " + content[i] + " ");
// }
// System.out.println("notice content: " + content);
byte[] dataBuf = new byte[data.getContent().size()] ;
data.getContent().buf().get(dataBuf,0,data.getContent().size()) ;
// Base64.Encoder base64Encoder = Base64.getMimeEncoder();
// String dataContentBase64 = base64Encoder.encodeToString(dataBuf);
String plainText = null ;
try {
plainText = Aes.newDecrypt(dataBuf,Aes.getDefaultKey()) ;
} catch (Exception e) {
e.printStackTrace();
}
responseData.setFileSlice(plainText.getBytes(StandardCharsets.UTF_8));
dataCacheQueue.setResponseData(dataReqId, responseData);
// 重置其超时次数记录
if (timeOutNums.containsKey(dataReqId)) {
timeOutNums.remove(dataReqId);
}
}
}, handleInterestTimeOutAndNack, handleInterestTimeOutAndNack);
} else if(orderPrefix.equals("/timeSync")||orderPrefix.equals("/register")){
face.expressInterest(interest, new OnData() {
@Override
public void onData(Interest interest, Data data) {
byte[] dataBuf = new byte[data.getContent().size()];
data.getContent().buf().get(dataBuf, 0, data.getContent().size());
responseData.setResponseData(data.getContent().toString());
dataCacheQueue.setResponseData(dataReqId, responseData);
// 重置其超时次数记录
if (timeOutNums.containsKey(dataReqId)) {
timeOutNums.remove(dataReqId);
}
}
},handleInterestTimeOutAndNack, handleInterestTimeOutAndNack);
}else {
face.expressInterest(interest, new OnData() {
@Override
public void onData(Interest interest, Data data) {
// System.out.println("on data success");
// TODO Auto-generated method stub
// System.out.println("ondata interest: "+interest.getName());
// System.out.println("ondata data: "+data.getContent().toString());
byte[] dataBuf = new byte[data.getContent().size()] ;
data.getContent().buf().get(dataBuf,0,data.getContent().size()) ;
// Base64.Encoder base64Encoder = Base64.getMimeEncoder();
// String dataContentBase64 = base64Encoder.encodeToString(dataBuf);
String plainText = null ;
try {
plainText = Aes.newDecrypt(dataBuf,Aes.getDefaultKey()) ;
} catch (Exception e) {
e.printStackTrace();
}
responseData.setResponseData(plainText);
dataCacheQueue.setResponseData(dataReqId, responseData);
// 重置其超时次数记录
if (timeOutNums.containsKey(dataReqId)) {
timeOutNums.remove(dataReqId);
}
}
}, handleInterestTimeOutAndNack, handleInterestTimeOutAndNack);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
// 写头像
// public Integer writeHeadPhotoIntoLocalFile(String filenameString,
// Integer sliceNo,Integer sliceSize,byte[] bytes) {
// String pathString=mainApp.fileLocalPath;
// return writeIntoLocalFile(pathString, filenameString, sliceNo, sliceSize, bytes);
// }
// 根据包含路径的文件名获取纯文件名[linux下]
public static String getPureFileName(String pathfilename) {
// 标记最后一个/的下标
int indexLeft = -1;
for (int i = 0; i < pathfilename.length(); i++) {
if (pathfilename.charAt(i) == '/') {
indexLeft = i;
}
}
if (indexLeft == -1) {
System.out.println("pure name[linux]: " + pathfilename);
return pathfilename;
} else {
System.out.println("pure name[linux]: " + pathfilename.substring(indexLeft + 1, pathfilename.length()));
return pathfilename.substring(indexLeft + 1, pathfilename.length());
}
}
// 根据包含路径的文件名获取纯文件名[windows本地]
public static String getPureFileNameFromWindows(String pathfilename) {
// 标记最后一个/的下标
int indexLeft = -1;
for (int i = 0; i < pathfilename.length(); i++) {
if (pathfilename.charAt(i) == '\\') {
indexLeft = i;
}
}
if (indexLeft == -1) {
System.out.println("pure name[windows]: " + pathfilename);
return pathfilename;
} else {
System.out.println("pure name[windows]: " + pathfilename.substring(indexLeft + 1, pathfilename.length()));
return pathfilename.substring(indexLeft + 1, pathfilename.length());
}
}
// // 向指定本地文件写入指定数据分片=》被ondata调用
// public Integer writeIntoLocalFile(String pathString,String filenameString,
// Integer sliceNo,Integer sliceSize,byte[] bytes) {
// try {
// @SuppressWarnings("resource")
// RandomAccessFile randomAccessFile=new RandomAccessFile(pathString+filenameString, "rw");
// int contentSize=
// randomAccessFile.write(bytes,sliceNo*sliceSize,bytes.length);
// return 0;
// } catch (IOException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// return 1;
// }
// }
// 关闭数据连接
public void closeDataConn() {
this.face.shutdown();
}
// 解决处理兴趣包超时之后的重传问题[除上传下载外的兴趣包]
public class HandleInterestTimeOutAndNack implements OnTimeout, OnNetworkNack {
// 命令前缀
private String orderPrefix;
// 兴趣包
private Interest interest;
// 请求序列号
private Long dataReqId;
// 标记是否拿到网络回复(数据信息/超时信息):测试使用
public boolean isFinished = false;
public HandleInterestTimeOutAndNack(String orderPrefix, Interest interest, Long dataReqId) {
this.orderPrefix = orderPrefix;
this.interest = interest;
this.interest.setInterestLifetimeMilliseconds(2000);
this.dataReqId = dataReqId;
}
// 处理兴趣包超时
@Override
public void onTimeout(Interest interest) {
// 打印超时信息
System.out.println("########## Time out for interest " + interest.getName() + "###########");
// 记录此次丢包/超时
if (timeOutNums.containsKey(this.dataReqId)) {
int value = timeOutNums.get(this.dataReqId) + 1;
timeOutNums.put(this.dataReqId, value);
} else {
timeOutNums.put(this.dataReqId, 1);
}
// 根据是否多次超时,决定是否重传该兴趣包:暂时是全部重传
// 后期可以改作,超时次数超过阈值时候,
// 自拟定一个指定值放入数据回复缓存区,前端控制类收到该值,就
// 判定网络极其拥塞,进行弹窗提示。
if (!isInterestTimeOut(this.dataReqId)) {
// 超时次数没有超过阈值:重传该兴趣包
expressTheInterest(this.orderPrefix, this.interest, this.dataReqId);
} else {
// 超时次数超过阈值
System.out.println("该兴趣包的超时次数超过阈值:" + timeoutCeil + "!!!");
// 返回一个timeout信息放入datacache
ResponseData responseData = new ResponseData();
responseData.setPrefix(this.orderPrefix);
responseData.setResponseData(getWrongAnswerJson(timeoutCodeInteger, timeoutError));
dataCacheQueue.setResponseData(this.dataReqId, responseData);
}
// 打印重传信息
System.out.println("########## Resend the interest " + interest.getName() + "###########");
// 处理完成
isFinished = true;
}
// 处理收到一个Nack包
@Override
public void onNetworkNack(Interest interest, NetworkNack networkNack) {
// 打印超时信息
System.out.println("########## Nack for interest " + interest.getName()
+ ", Nack: " + networkNack.toString());
// 返回一个nack信息放入datacache
ResponseData responseData = new ResponseData();
responseData.setPrefix(this.orderPrefix);
responseData.setResponseData(getWrongAnswerJson(nackCodeInteger, nackError));
dataCacheQueue.setResponseData(this.dataReqId,responseData);
isFinished = true;
}
}
// 构造一个json,给前端返回一个可以进行JSON解析的错误信息
// 用以避免界面卡死
public static String getWrongAnswerJson(Integer wrongAnswerCode, String wrongAnswerString) {
JSONObject jsonObject = new JSONObject();
Integer code = wrongAnswerCode;
String errMsg = wrongAnswerString;
String data = "";
try {
jsonObject.put("code", code);
jsonObject.put("errMsg", errMsg);
jsonObject.put("data", data);
} catch (Exception e) {
// TODO: handle exception
System.out.println("exception: " + e.getMessage());
}
return jsonObject.toString();
}
}