银行前置机程序(通信部分socket,java编写 )


package Client;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;
import java.nio.channels.IllegalBlockingModeException;
import Config.ParameterCfg;
import ErrorExcp.ErrorExcp;
import Log.Log;
import Msg.Msg.Msg;
import MsgCfg.MsgGlobalInfo;

/**
*
* @author xiehui 通信类,数据的发送与接受
*
*/
public class Client {

/**
* 负责数据发送与接受的套接字
*/
public Socket ncpClient;
/**
* socket读取数据管道
*/
public OutputStream writeIO;
/**
* socket写数据管道
*/
public InputStream receiveIO;

/**
*日志记录
*/
public Log log;
/**
* 是否做了资源释放,避免二次释放引起bug,默认为假
*/

public boolean isCloseDeal = false;
/**
* 在套接字上获取的报文信息
*/
public MsgInfo msgInfo;

/**
* Client()函数为构造函数
*
* @param acccpetSocket
* :为服务器投递过来的套接字<br>
*
* log:为传递的日志对象,方便在通信的过程中将状态记录下来
*
* @return 没有返回值的内容
*
* @exception exceptions
* 没有异常被抛出
*/
public Client(Socket acccpetSocket, Log log) {

/**
* 套接字本地创建的,发起方是农产品前置机
*/
this.ncpClient = acccpetSocket;

this.log = log;
msgInfo = new MsgInfo();

/**
* 将发起的IP地址写入日志
*/
log.add(acccpetSocket.getRemoteSocketAddress());
}

/**
* 向服务器建立连接
*
* @param seconds
* :为向服务器发起连接的超时时间<br>
*
* errorSnd:为发送期间可能出现异常的对象,一旦发生异常,完善异常对象信息然后抛出
*
* @return 没有返回值的内容
* @throws ErrorExcp
*
* @exception ErrorSend
* 抛出一个发送数据的异常
*/

public void conncet() throws ErrorExcp

{

try {

/**
* 从程序全局配置参数取出地址(地址,连接超时时间)
*/
ncpClient.connect(ParameterCfg.bankAdreess,
ParameterCfg.conncetTime);

} catch (IllegalArgumentException e) {

ErrorExcp error = new ErrorExcp(2, 1, 3, 301, "conncet");
throw error;
} catch (UnknownHostException e) {

ErrorExcp error = new ErrorExcp(2, 1, 3, 302, "conncet");
throw error;
} catch (IllegalBlockingModeException e) {

ErrorExcp error = new ErrorExcp(2, 1, 3, 303, "conncet");
throw error;

} catch (SocketTimeoutException e) {

ErrorExcp error = new ErrorExcp(2, 1, 3, 304, "conncet");
throw error;

} catch (IOException e) {

ErrorExcp error = new ErrorExcp(2, 1, 3, 305, "conncet");
throw error;

} finally {
close();
}

}

public void checkIsClose(int result, int errorCode, String info)
throws ErrorExcp {
if (ncpClient.isClosed()) {

ErrorExcp error = new ErrorExcp(1, result, 3, errorCode, info);
throw error;

}

}

/**
* 从套接字上发送一个字节数组
*
* @param sendByte
* : 为要发送的字节数组对象<br>
*
* start : 为尝试从sendByte的第start个字节开始发送<br>
*
* end : 表示发到到sendByte的第end个字节结束
*
* @return 没有返回值的内容
*
* @exception IllegalBlockingModeException
* 抛出一个使用了非阻塞套接字的异常<br>
* IOException 发送失败抛出一个IO异常(可能是网络突然中断)
*
*/
public void send(byte[] sendByte, int start, int end)
throws IllegalBlockingModeException, IOException {

writeIO = ncpClient.getOutputStream();
writeIO.write(sendByte, start, end);
writeIO.flush();

}

/**
* 在套接字上接受数据
*
* @param receviceMsg
* :表示要接受的报文字节数组
* @param start
* :表示从报文字节数组的哪一位直接序列开始接受
* @param end
* :表示从报文字节数组的哪一位结束数据的接受
* @return :返回接受了多少个字节的数据
* @throws ErrorExcp
* :如果接受时发现连接已经中断,抛出异常
* @throws IOException
* :如果接受数据异常,抛出IO异常
*/

private int receive(byte[] receviceMsg, int start, int end)
throws ErrorExcp, IOException

{
int length = -1;

receiveIO = ncpClient.getInputStream();
length = receiveIO.read(receviceMsg, start, end);

return length;
}

/**
* 发送报文数据的适配接口
*
* @param msg
* @throws ErrorExcp
*/
public void sendMsg(Msg msg) throws ErrorExcp

{

try {
send(msg.stdByte, 0, msg.stdByte.length);

} catch (IllegalBlockingModeException e) {

close();
ErrorExcp error = new ErrorExcp(2, 1, 3, 303, "SendMsg");
throw error;
}

catch (IOException e) {

close();
ErrorExcp error = new ErrorExcp(2, 1, 3, 305, "SendMsg");

throw error;
} catch (NullPointerException e) {

close();
ErrorExcp error = new ErrorExcp(2, 1, 3, 307, "SendMsg");
throw error;

}

}

/**
* 在套接字上收取一个报文
*
* @return
* @throws ErrorExcp
*/
public MsgInfo readMsg() throws ErrorExcp {

try {
/**
* 设置接受超时时间
*/
setRecTime();
/**
* 创建四个字节的数组,接受报文的msglength字段
*/
byte[] msgLength = new byte[4];

/**
* 接受头4个字节,并获取接受的直接的长度
*/

int recHeadLength = receive(msgLength, 0, 4);

/**
* 判断头4个字节的数据包是否接受完整
*/

if (recHeadLength != 4) {

ErrorExcp error = new ErrorExcp(1, 1, 1, 402, "msgLength");
throw error;

}

/**
* 将头4个字节写入日志
*/
log.addMsgHead(msgLength);

/**
* 写入报文长头四个字节信息
*/
msgInfo.msgLength = new String(msgLength);
/**
* 检查报文全局信息配置
*/
MsgGlobalInfo.macheingMsgLength(msgInfo);

int length = Integer.valueOf(msgInfo.msgLength);

/**
* 收取除报文头四个字节字段以外的全部报文
*/
byte rec[] = new byte[length];
/**
* 准备判断接受报文的长度是否达到期望的字节长度
*/
int recBodyLength;

recBodyLength = receive(rec, 0, length);

/**
* 判断数据包除头msgLength外,其他字段的长度是否正确
*/
if (recBodyLength != length) {
ErrorExcp error = new ErrorExcp(1, 1, 1, 404, "stdByte");
throw error;

}
String msgBody = new String(rec, 0, recBodyLength);
/**
* 将报文体写入日志
*/
log.addMsgBody(msgBody);
/**
* 完整的报文
*/
msgInfo.stdStr = msgInfo.msgLength + msgBody;

/**
* 写入报文编号信息
*/
msgInfo.msgNum = msgInfo.stdStr.substring(38, 41);

}
/**
* 捕捉连接中断的信息
*/
catch (IOException e) {
ErrorExcp error = new ErrorExcp(1, 1, 3, 407, "ReadMsg");
throw error;
}

return msgInfo;

}

/**
* 设置接受数据超时时间
*
* @throws ErrorExcp
*/
public void setRecTime() throws ErrorExcp {
try {
ncpClient.setSoTimeout(ParameterCfg.recTime);

} catch (SocketException e) {
ErrorExcp error = new ErrorExcp(2, 1, 3, 408, "setRecTime");
throw error;
}

}

public void close()

{

try {
/**
* 如果以前在catch 释放了则不需要在finally再次释放,否则可能会引发错误
*/
if (!isCloseDeal && !ncpClient.isClosed()) {

ncpClient.close();

}

} catch (Exception e) {

}

finally {
ncpClient = null;
isCloseDeal = true;
}

}

}




package Client;

import ErrorExcp.ErrorExcp;
import Msg.Msg.Msg;

/**
* 数据的接受与发送的抽象类
*
*/
public abstract class RecAndSnd

{
/**
* 缓存的日志对象
*/
public StringBuffer logInfo;

/**
* 通信对象
*/
public Client client;

/**
* 在套接字上发送一个报文
*
* @param msg
* 报文对象
* @throws ErrorExcp
*/
public abstract void send(Msg msg) throws ErrorExcp;

/**
* 在套接字上接受一个报文
*
* @return 报文对象Msg
* @throws ErrorExcp
*/
public abstract Msg read() throws ErrorExcp;

}




package Client;

import java.net.Socket;
import ErrorExcp.ErrorExcp;
import Log.Log;
import Msg.Msg.Msg;
import Msg.Msg.MsgFactory;

public class RecToSnd extends RecAndSnd

{

public RecToSnd(Log log, Socket accptSocket) {

client = new Client(accptSocket, log);

}

public void send(Msg msg) throws ErrorExcp {

try {

/**
* 检查发送前的连接是否正常
*/
client.checkIsClose(1, 306, "send");
client.sendMsg(msg);
}
/**
* 无论如何,对于银行发起的交易,应该断开连接
*/
finally {
client.close();
}

}

public Msg read() throws ErrorExcp

{
Msg msg = null;
MsgInfo msgInfo = null;
/**
* 接受套接字上的报文信息
*/
msgInfo = client.readMsg();

// /**
// * 如果非debug模式下,那么关闭连接(因为不需要应答)
// */
// if (!ParameterCfg.debug)
// {
// client.close();
// }

msg = MsgFactory.CreatMsg(msgInfo);
return msg;

}

}




package Client;

import ErrorExcp.ErrorExcp;
import Log.Log;
import Msg.Msg.Msg;
import Msg.Msg.MsgFactory;
import MsgCfg.MsgCfg;

/**
* 农产品发起交易时用到的通信类
*
*/
public class SndToRec extends RecAndSnd {

public MsgCfg msgCfg;

private SocketPool pool;

/**
* 从池中取出一个socket对象
*
* @param log
*/
public SndToRec(Log log) {
pool = SocketPool.getInstance();

client = new Client(pool.get(), log);

}

public void send(Msg msg) throws ErrorExcp {
/**
* 与银行服务器进行连接
*/
client.conncet();
/**
* 在套接字上发送一个报文
*/
client.sendMsg(msg);

}

/**
* 在套接字上接受发送后,银行返回的报文的信息
*
* @return 报文相关的信息
* @throws ErrorExcp
*/

public Msg read() throws ErrorExcp

{
Msg msg = null;

MsgInfo msgInfo = null;
try {

/**
* 检查连接是否正常
*/
client.checkIsClose(2, 406, "read");

msgInfo = client.readMsg();

} catch (ErrorExcp e) {
/**
* 因为是农产品发起的交易,没有收到数据,所以状态未明确
*/
e.result = 2;
throw e;

} finally {
client.close();
}
/**
* 如果出现接受的报文,不是发送报文所对应的报文应该报错,从此位置开始报文接受工作已经全部 完成
*/

if (msgCfg.relativeList.indexOf(msgInfo.msgNum) == -1) {

ErrorExcp error = new ErrorExcp(1, 1, 3, 501, "msgNum");
throw error;

}

/**
* 通过报文工厂创建报文
*/
msg = MsgFactory.CreatMsg(msgInfo);

return msg;

}

}
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值