JAVA Mina中使用Xmodem1k协议发送文件进行远程升级

一、xdmodem1k的具体协议介绍这里不再做详细的解释只简单描述

    xmodem1k协议发送数据的数据包格式:

   <STX><包序号><包序号反码><文件数据(1024字节)><校验位>

0x02

STX: 包头

0x04

EOT: 结束文件传输

0x06

ACK: 正常响应,如:数据包正确接收

0x15

NACK: 非正常响应

0x18

CAN: 取消文件传输

0x43

C: ASCII字符C

二、xmodem1k发送的流程(Mina socket作为发送方)

1:建立Socket连接

2:接收方发送C到服务端   0x43

3:服务端接收到43开始解析文件发送第一帧包的数据到接收方

4:接收方收到正确数据返回0x06即ACK

6:如果发送方收到0x15则需要重发上一次发的包

7:如果发送方收到0x18则需要无条件终止发送,出现了严重错误。


三、JAVA代码示例:

   // 开始
    private final byte SOH = 0x01;
    // 结束
    private final byte EOT = 0x04;
    // 应答
    private final byte ACK = 0x06;
    // 重传
    private final byte NAK = 0x15;
    // 无条件结束

    private final byte CAN = 0x18;

   // 开始

    private  final byte STX=0x02;

    // 以128字节块的形式传输数据
    private final int SECTOR_SIZE = 1024;
    // 最大错误(无应答)包数

    private final int MAX_ERRORS = 10;

   //path要发送的文件的路径,deviceNo是设备唯一编号

   public void saveXmodemData(Path path,String deviceNo){
       // 包序号
        byte blockNumber = 0x01;
        // 校验和
        int checkSum;
        // 读取到缓冲区的字节数量
        int nbytes;
        // 初始化数据缓冲区
        byte[] sector = new byte[SECTOR_SIZE];
        int num=1;
        try {
    DataInputStream inputStream = new DataInputStream(Files.newInputStream(path));
    IoBuffer iobuffer=null;
     
    while ((nbytes = inputStream.read(sector)) > 0) {
        int inputLenth=inputStream.available();
          // 如果数据包小于1024个字节,以0x1A补齐 
          if (nbytes < SECTOR_SIZE) {
                 for (int i = nbytes; i < SECTOR_SIZE; i++) {
                sector[i] = (byte) 0x1A;
                 }
             }
          StringBuffer result=new StringBuffer();
          result.append(HexUtil.BytetoHexString(STX));
          result.append(HexUtil.BytetoHexString(blockNumber));
          result.append(HexUtil.BytetoHexString(((byte)~blockNumber)));
          result.append(HexUtil.Bytes2HexString(sector));
          String checkNum=byteToCrcNum(HexUtil.Bytes2HexString(sector));
          result.append(checkNum);
           byte[] resultData=HexUtil.HexString2Bytes(result.toString());

         //可以根据设备编号和序列将resultData保存起来,后面在Handler类中根据接收方返回的数据

         //根据序号排序发送给设备

           save(resultData,deviceNo,blockNumber);

             blockNumber = (byte) ((++blockNumber) % 256);
             result=null;
          }
          inputStream.close();
       } catch (Exception e) {

      log.error("{保存升级数据错误}");

           //其他业务处理

       } 

   } 

注意:上面方式中的byteToCrcNum这个方式是用于计算他们的CRC16的效验,将16进制字符串转成字节数组计算CRC16的效验码。

 private String byteToCrcNum(String HexStr){
String listStr=HexStr.replaceAll(" ","")
byte[] data=HexUtil.HexString2Bytes(listStr);
  Long checkNumCrc=new CRC16().calcCRC(data);
String HexNum=Long.toHexString(checkNumCrc);
 
return padLeft(HexNum,4).toUpperCase();//不足4位的左边自动补充0
   }

至于收到接收端以后发送数据写到mina的Handler类里面去。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值