|

493精币
/**
* 模拟连接TravelSky的Eterm的客户Duan
*
* @author hech
*
*/
public class Eterm implements EtermClient {
static final Logger logger = LoggerFactory.getLogger(P350Eterm.class.getName());
/**
* socket
*/
private Socket socket = null;
/**
* EtermConfig
*/
private SaEterm config = null;
/**
* 输出流
*/
BufferedOutputStream out;
/**
* 输入流
*/
BufferedInputStream in;
/**
* 同步锁
*/
private ReentrantLock locker = new ReentrantLock();
/**
* 锁条件变量
*/
private Condition lockCondition = locker.newCondition();
/**
* 锁定标记
*/
boolean isLocked = false;
/**
* 是否连接上
*/
private boolean isConnected;
/**
* 实时信息对象
*/
private EtermRealtimeInfo realtimeInfo = null;
/**
* 协议
*/
private P350EtermProtocol protocol = new P350EtermProtocol();
/**
* ips列表
*/
private String[] ips = null;
/**
* 随机种子
*/
private Random random = new Random();
/**
* 默认构造器,传入EtermConfig
*
* @param config
*/
public P350Eterm(SaEterm config,String[] ips) {
this.config = config;
this.ips = ips;
this.realtimeInfo = new EtermRealtimeInfo();
}
/**
* 获得一个随机ip
*/
private String getRandomIp(){
if (ips.length==0)
return null;
else
return ips[random.nextInt(ips.length)];
}
/**
* 锁定整个实例的访问 在这里,其实并没有使用ReentrantLock做实例锁定,而是使用它做了lock方法本身的锁定
* 因为ReentrantLock是基于线程的,所以如果出现死锁状态,无法使用外线程方便的解锁
*
* @throws InterruptedException
*
*/
public void lock() {
this.realtimeInfo.setLastLockedTime(System.currentTimeMillis());
this.realtimeInfo.addOneQueueCount();
this.locker.lock();
try {
while (isLocked)
lockCondition.await();
isLocked = true;
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
this.locker.unlock();
}
}
/**
* 解锁对整个实例的访问,此方法必须在finally块中 在此处没有加入对解锁条件的支持,主要是考虑系统可以无条件解任何锁
*/
public void unlock() {
this.realtimeInfo.setLastIdleTime(System.currentTimeMillis());
this.realtimeInfo.removeOneQueueCount();
new DelayedUnLocker().start();
}
/**
* 延时解除锁定
*
* @author zhangjin
*
*/
class DelayedUnLocker extends Thread {
public void run() {
try {
Thread.sleep(config.getOperInterval());
} catch (InterruptedException e) {
e.printStackTrace();
}
locker.lock();
try {
isLocked = false;
lockCondition.signal();
} finally {
locker.unlock();
}
}
}
/**
* 获得当前配置信息字符串
*
* @return
*/
public String getConfigInfo() {
return this.config.getUsername() + "@" + this.config.getHost() + ":" + this.config.getPort() + "|" + this.config.getOfficeId() + "|" + this.config.getSiUsername();
}
/**
* 获得配置信息
*/
public SaEterm getConfig() {
return config;
}
/**
* 获得实时信息
*/
public EtermRealtimeInfo getRealtimeInfo() {
return this.realtimeInfo;
}
/**
* 是否能连接
*
* @return
*/
public boolean isConnected() {
return isConnected && socket != null && out != null & in != null;
}
/**
* 关闭连接
*
*/
public void disConnect() {
isConnected = false;
try {
if (out != null)
out.close();
out = null;
} catch (Exception e) {
e.printStackTrace();
}
try {
if (in != null)
in.close();
in = null;
} catch (Exception e) {
e.printStackTrace();
}
try {
if (socket != null)
socket.close();
socket = null;
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 重新连接
*
*/
public void reConnect() {
disConnect();
connect();
}
/**
* 连接服务器
*
* @throws UnknownHostException
* @throws IOException
*/
public String connect() {
// 如果已经连接,则不用连接了
if (isConnected())
return "已连接";
// System.out.println(_username+"/"+_password);
String retdata = "连接失败,未知原因";
try {
socket = new Socket();
socket.connect(new InetSocketAddress(InetAddress.getByName(config.getHost()), config.getPort()), 30 * 1000);
// socket.setTcpNoDelay(true);
socket.setSoTimeout(30 * 1000);
out = new BufferedOutputStream(socket.getOutputStream());
in = new BufferedInputStream(socket.getInputStream());
byte[] data = protocol.getLoginData(config.getUsername(), config.getPassword());
// System.out.println("正在连接:"+host+":"+port+",使用帐户"+username+"/"+password);
out.write(data);
out.flush();
EtermData edata = protocol.parseEtermData(new EtermData(null), in);
if (protocol.checkLogin(edata.getSource())) {
// 说明登陆成功
out.write(protocol.getLoginSend17());
out.flush();
// 返回132字节的握手数据
protocol.parseEtermData(new EtermData(null), in);
// 发送握手数据,34字节
out.write(protocol.getLoginSend34());
out.flush();
protocol.parseEtermData(new EtermData(null), in);
out.write(protocol.getLoginSend260());
out.flush();
//protocol.parseEtermData(new EtermData(null), in);
//protocol.parseEtermData(new EtermData(null), in);
// 发送握手数据,68字节
out.write(protocol.getLoginSend68());
out.flush();
// 返回通知数据,中航信通知数据
edata = protocol.parseEtermData(new EtermData(null), in);
// 发送si的数据,因为不能自动登录
siLogin();
isConnected = true;
} else {
// 其他失败
retdata = "连接失败," + edata.getData();
throw new Exception();
}
} catch (Exception e) {
retdata = "连接失败," + e.toString();
this.disConnect();
e.printStackTrace();
}
boolean isSuccessed = isConnected();
if (isSuccessed)
retdata = "连接成功";
// 累加connectCount计数
this.realtimeInfo.addConnectCount(1);
if (!isSuccessed)
this.realtimeInfo.addConnectErrorCount(1);
return retdata;
}
/**
* si登陆
*
* @throws Exception
*/
public EtermData siLogin() throws Exception {
String cmd = null;
if (!config.getSiUsername().equals("") && !config.getSiPassword().equals("")) {
cmd = "si:" + config.getSiUsername() + "/" + config.getSiPassword() + (config.getSiLevel().equals("") ? "" : ("/" + config.getSiLevel()));
}
if (cmd != null)
return internalSendCMD(cmd, new EtermData(cmd), false, false);
else
return null;
}
/**
* 发送命令
*
* @return
* @throws IOException
*/
private EtermData internalSendCMD(String cmd, EtermData edata, boolean getSource, boolean checkSequence) throws Exception {
long start = System.currentTimeMillis();
byte[] senddata = protocol.getSendData(cmd);
out.write(senddata);
out.flush();
if (checkSequence)
edata = protocol.checkedParseEtermData(edata, in);
else
edata = protocol.parseEtermData(edata, in);
// 累加write/read Bytes。
this.realtimeInfo.addWriteBytes(senddata.length);
if (edata.source != null)
this.realtimeInfo.addReadBytes(edata.getSource().length);
// 设定serviceCount
this.realtimeInfo.addServiceCount(1);
// 设定活动时间
this.realtimeInfo.addActiveTime(System.currentTimeMillis() - start);
if (edata != null && !getSource)
edata.source = null;
return edata;
}
/**
* 发送数据
*
* @param cmd
* @return
*/
public EtermData sendCMD(String cmd, boolean getSource) {
return sendCMD(cmd, config.getMaxTryTimes(), getSource);
}
/**
* 发送数据
*
* @param cmd
* @param retrySendDataLImit
* @return
*/
public EtermData sendCMD(String cmd, int retrytimes, boolean getSource) {
EtermData edata = new EtermData(cmd);
// 要重试多次,防止有问题
for (int trytimes = 0; trytimes < retrytimes; trytimes++) {
try {
edata = internalSendCMD(cmd, edata, getSource, true);
} catch (Exception e) {
System.out.println(edata.data);
e.printStackTrace();
// 网络连接不上的问题,重新连接
logger.info("pid(" + config.getId() + ")关联的终端信息:" + getConfigInfo() + "遇到异常"+e.toString()+",正在重新连接...");
reConnect();
}
if (edata.data != null && edata.data.indexOf("PLEASE WAIT - TRANSACTION IN PROGRESS") == -1) {
edata.success = true;
break;
}
// 增加失败计数
this.realtimeInfo.addServiceErrorCount(1);
edata.retryTimes++;
try {
Thread.sleep(50);
} catch (InterruptedException e) {
}
}
return edata;
}
}
|
|