银行前置机程序(通信部分socket,java编写 )
发布日期:2021-09-18 01:37:00 浏览次数:6 分类:技术文章

本文共 7775 字,大约阅读时间需要 25 分钟。

2009年10月31日 星期六 15:32

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 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:关于RUP的理论笔记
下一篇:CMMI5在项目中的精简应用

发表评论

最新留言

路过,博主的博客真漂亮。。
[***.116.15.85]2024年04月08日 03时58分54秒