本文共 7775 字,大约阅读时间需要 25 分钟。
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; /*** 数据的接受与发送的抽象类* * @author xiehui* */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;
/*** 农产品发起交易时用到的通信类* * @author xiehui* * */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; } } |
来自:
转载地址:https://blog.csdn.net/yuezu1026/article/details/5270667 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!