河南普通公路智慧公路标准外场设施部分终端与平台传输协议Socket TcpClient上报数据

前言

通讯方式TCP:每个设备建立一个TCP长连接,无数据时需要60秒发送心跳包,有数据时按照要求发送数据:

数据包结构:

7E 消息头(36Bytes) 消息体 CRC 7E

*消息头 消息体 中出现0x7E 需要转化为0x7D 0x02 , 出现0x7D 转化为 0x7D 0x01

*消息体需要使用SM4加密,密文统一使用zhgl(7a68676c000000000000000000000000)

*CRC校验消息头和消息体内容

1加密消息体 2 CRC 3转化

SM4加密:java sm4国密算法加密、解密 - Marydon - 博客园

需要添加的功能模块:

数据库通道信息中,添加发送时的设备编号。无需发送的设备编号为空字符串。

读取信息时将设备编号也读到内存并添加是否已鉴权成功socket的标记位。

在设备采集到数据时,判断通道是否需要发送数据,需要发送的话则计算后进入发送流程。

需要添加的数据模块:

添加通道信息和发送数据用的socket对应的MAP

添加通道信息和待额外补发数据的链表对应的MAP

发送数据流程:

(未注册socket)

  1. 发送注册包注册,等待注册包回复
  2. 发送鉴权包,等待鉴权包回复,成功就保持连接发送之后数据,失败则断开连接,等候30秒重新连接发送。

(已注册socket)

  1. 发送传感器数据信息,并等待回复,回复成功则继续;失败则将数据存储进缓冲中过10秒之后继续发送,连续失败三次断开连接下次需要发送数据时重新连接
  2. 失败的数据包都存储入缓冲数据列中,在之后成功发送数据之后依次发送掉。

消息头:(36个字节)

0x07 命令码 消息体长度(数据包为:0x00 0x00 0x00 0x12) 0x01 0x01 0x01 消息流水号(每个设备每天累加)设备编号(设备编号excel中的编号) 时间(YYYYMMDDhhmmss共7位:20 20-07-15 17:30:35 表示为0x14 0x14 0x07 0x0F 0x11 0x1E 0x23)

注册包消息体:

命令码:0x01

0x16(或0x19) YSB(补两个空格) AIOTYB(补0x00补足20位),设备编号(设备编号excel中的编号) 0x405C82703AFB7E91(经度) 0x404178C7E28240B8(纬度)  ip(ipV4 4位后面补0x20补足16位) 0x00 0x3C 0x00 0x00 0x00 0x32 0x30 0x32 0x31 0x30 0x01 0x30 0x01

平台返回鉴权码:

0x7E 命令字 鉴权码 0x7E

鉴权包消息体:

命令码:0x02

消息体平台返回鉴权码:不足32位的补0x20补20个空格

心跳包消息体:

命令码:0x03

消息体为空

准消息体:(17个字节)

命令码:0x16

数据包主内容:0x00 0x01 P001 Z 0000000000

0x00 0x01为2个byte数值,红色部分为字符串需要再转化为byte再输出

P001:传感器编号(固定值)

Z:正数,如果结果为负数则写F

0000000000:挠度值(10个字节)0000000000-9999999999表示00000.00000mm到99999.99999mm

应变消息体:(17个字节)

命令码0x19

数据包内容:0x00 0x01 Y001 Z 0000000000

Y001:传感器编号(固定值)

Z:正数,如果结果为负数则写F

0000000000:挠度值(10个字节)0000000000-9999999999表示00000.00000με到99999.99999με

package TCPserver;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.Socket;
import java.net.URL;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Map;

import com.AIOT.utils.Sm4Util;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;

public class SocketUtil {
    //public static Map<String,Map<String,NumberNowDate>> dateMap = new HashMap<String,Map<String,NumberNowDate>>(); //nowData ->NumberDate
    public static Map<String,Integer> numberMap = new HashMap<String,Integer>();//设备编号->消息流水
    public static final String Y_M_D_H_M_S = "yyyyMMdd HHmmss";
    
    public final static byte [] packge ={0x5a,0x20,0x00,0x11,0x11};//0注册包1鉴权包2心跳包3水准消息体4应变消息体
    public final static byte [] codePackge ={0x01,0x02,0x03,0x16,0x19};//同上 命令码
    public static byte [] codeLength={0x00,0x00,0x00,0x00};
    public static byte [] codeLength3={0x01,0x01,0x01};//00不加密 01加密
    public static byte [] typePackege={0x1,0x19};//0水准1应变
    public static String [] flag ={"Z","F"};//Z正数F负数
    
    public static Map<String, Socket> ipMap = new HashMap<String, Socket>();//通道信息对应socket
    
    /**
     * 消息头
     * 
     * @param flag
     * @param EquipmentNumber
     * @return
     * @throws Exception
     */
    public static byte[] getMessageHeader(int flag, String EquipmentNumber) {
        byte[] head = new byte[36];
        codeLength[3] = packge[flag];
        byte[] code2 = codeLength;
        byte[] code1 = { 0x07, codePackge[flag], code2[0], code2[1], code2[2], code2[3], codeLength3[0], codeLength3[1],
                codeLength3[2] };// code1(code2)共9
        byte[] code4 = uint16ToBytes(getDowDateNum(EquipmentNumber));// 流水号
        byte[] code5 = EquipmentNumber.getBytes();// 设备编号18
        Calendar cal = Calendar.getInstance();
        int year = cal.get(Calendar.YEAR);
        int month = cal.get(Calendar.MONTH) + 1;
        int day = cal.get(Calendar.DATE);
        int hour = cal.get(Calendar.HOUR_OF_DAY);
        int min = cal.get(Calendar.MINUTE);
        int sec = cal.get(Calendar.SECOND);
        byte[] code6 = { (byte) (year / 100), (byte) (year % 100), (byte) month, (byte) day, (byte) hour, (byte) min,
                (byte) sec };
        System.arraycopy(code1, 0, head, 0, 9);
        System.arraycopy(code4, 0, head, 9, 2);
        System.arraycopy(code5, 0, head, 11, 18);
        System.arraycopy(code6, 0, head, 29, 7);

        return head;
    }
    
    /**
     * 注册包消息体
     * @param flag
     * @param EquipmentNumber
     * @return
     */
    public static byte[]  getRegistrationPackageMessageBody(String EquipmentNumber){
        byte[] head = new byte[90];
        byte [] code1 = {0x07,'Y','S','B',' ',' ','A','I','O','T','Y','B',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '};//26
        byte [] code2 = EquipmentNumber.getBytes();//设备编号18
        byte [] code3 = {0x40,0x5C,(byte) 0x82,0x70,0x3A,(byte) 0xFB,0x7E,(byte) 0x91,0x40,0x41,0x78,(byte) 0xC7,(byte) 0xE2,(byte) 0x82,0x40,(byte) 0xB8};//16
        //String ip = getIP();
        String ip = "0.0.0.0";
        String[] split = ip.split("\\.");
        byte [] code4 ={0x00,(byte) Integer.parseInt(split[0]),(byte) Integer.parseInt(split[1]),(byte) Integer.parseInt(split[2]),(byte) Integer.parseInt(split[3]),' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',0x00,0x3C,0x00,0x00,0x00,0x32,0x30,0x32,0x31,0x30,0x31,0x30,0x31};//30
        System.arraycopy(code1, 0 , head , 0, 26);
        System.arraycopy(code2, 0 , head , 26, 18);
        System.arraycopy(code3, 0 , head , 44,16);
        System.arraycopy(code4, 0 , head , 60,30);
        return head;
    }
    
    /**
     * 鉴权包消息体
     * @return
     * @throws Exception 
     */
    public static byte[] getAuthenticationPacketMessageBody(byte[] codeToken,int flag,String EquipmentNumber) throws Exception{
        byte[] messageHeader = getMessageHeader(flag, EquipmentNumber);//获得消息头
        
        byte[] key = {0x7a,0x68,0x67,0x6c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
        byte[]    cipher = Sm4Util.encryptEcb(key, codeToken);//加密后的消息体
        
        byte[] addBytes = addBytes(messageHeader, cipher);//合并消息头消息体
        
        int crc2 = CRC16.calcCrc16(addBytes);//CRC校验
        byte[] uint16ToBytes = uint16ToBytes(crc2);
        
        byte[] addAllBytes = addBytes(addBytes,uint16ToBytes);
        byte[] index = check7DGetNewArray(addAllBytes);
        byte[] index1 = check7EGetNewArray(index);
        
        byte[] startArray = {0x7E};
        byte[] endArray = {0x7E};
        byte[] endAllBytes = addAllBytes(startArray,index1,endArray);
        
        return endAllBytes;
    }
    
    /**
     * 心跳包消息体
     * @throws Exception 
     */
    public static byte[]  sendHeartbeatPacketMessageBody(int flag,String EquipmentNumber){
        byte[] messageHeader = getMessageHeader(flag, EquipmentNumber);//获得消息头
        int crc2 = CRC16.calcCrc16(messageHeader);//CRC校验
        byte[] uint16ToBytes = uint16ToBytes(crc2);
        
        byte[] addAllBytes = addBytes(messageHeader, uint16ToBytes);
        byte[] index = check7DGetNewArray(addAllBytes);
        byte[] index1 = check7EGetNewArray(index);
        
        byte[] startArray = {0x7E};
        byte[] endArray = {0x7E};
        byte[] endAllBytes = addAllBytes(startArray,index1,endArray);
        return endAllBytes;
    }
    
    /**
     * 发送完整的注册包
     * @param head
     * @param flag
     * @param EquipmentNumber
     * @return
     * @throws Exception
     */
    public static byte[] getRegistrationPackageAllMessage(byte[] head,int flag,String EquipmentNumber) throws Exception{
        byte[] registrationPackageMessageBody = getRegistrationPackageMessageBody(EquipmentNumber);//获取消息体
        //消息体加密
         // 自定义的32位16进制密钥
        byte[] key = {0x7a,0x68,0x67,0x6c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
        byte[]    cipher = Sm4Util.encryptEcb(key, registrationPackageMessageBody);//加密后的消息体
        Sm4Util.decryptEcb(key, cipher);
        byte[] addBytes = addBytes(head, cipher);//合并消息头消息体
        int crc2 = CRC16.calcCrc16(addBytes);//CRC校验
        byte[] uint16ToBytes = uint16ToBytes(crc2);
        byte[] addAllBytes = addBytes(addBytes, uint16ToBytes);
        byte[] index = check7DGetNewArray(addAllBytes);
        byte[] index1 = check7EGetNewArray(index);
        byte[] startArray = {0x7E};
        byte[] endArray = {0x7E};
        byte[] endAllBytes = addAllBytes(startArray,index1,endArray);
        return endAllBytes;
    }
    
    /**
     * 水准消息体
     * @throws Exception 
     */
    public static byte[] sendSqvMessageBody(String EquipmentNumber,double data) throws Exception{
        byte[] head = getMessageHeader(3, EquipmentNumber);//获得消息头
        byte[] result = new byte[17];
        byte[] code0 ={0x00,0x01};
        String str ="P001";
        if(data>0.0 || data==0.0){
            str+=flag[0];
        }else{
            str+=flag[1];
        }
        String formate=String.format("%05d",Integer.parseInt(String.valueOf(data).split("\\.")[0]));
        str+=formate;
        String formate1=String.format("%.5f",data);
        formate1=formate1.split("\\.")[1];
        str+=formate1;
        byte[] code1 = str.getBytes();
        System.arraycopy(code0, 0 , result , 0, 2);
        System.arraycopy(code1, 0 , result , 2, 15);
        
        // 自定义的32位16进制密钥
        byte[] key = {0x7a,0x68,0x67,0x6c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
        byte[]    cipher = Sm4Util.encryptEcb(key, result);//加密后的消息体
        
        byte[] addBytes = addBytes(head, cipher);//合并消息头数据消息体
        int crc2 = CRC16.calcCrc16(addBytes);//CRC校验
        byte[] uint16ToBytes = uint16ToBytes(crc2);
        
        byte[] addAllBytes = addBytes(addBytes, uint16ToBytes);
        
        byte[] index = check7DGetNewArray(addAllBytes);
        byte[] index1 = check7EGetNewArray(index);
        
        byte[] startArray = {0x7E};
        byte[] endArray = {0x7E};
        byte[] endAllBytes = addAllBytes(startArray,index1,endArray);
        return endAllBytes;  
    }
    
    public static byte[] sendDvwMessageBoby(String EquipmentNumber,double data) throws Exception{
        byte[] head = getMessageHeader(4, EquipmentNumber);//获得消息头
        byte[] result = new byte[17];
        byte[] code0 ={0x00,0x01};
        String str ="Y001";
        if(data>0.0 || data==0.0){
            str+=flag[0];
        }else{
            str+=flag[1];
        }
        String formate=String.format("%05d",Integer.parseInt(String.valueOf(data).split("\\.")[0]));
        str+=formate;
        String formate1=String.format("%.5f",data);
        formate1=formate1.split("\\.")[1];
        str+=formate1;
        byte[] code1 = str.getBytes();
        System.arraycopy(code0, 0 , result , 0, 2);
        System.arraycopy(code1, 0 , result , 2, 15);
        // 自定义的32位16进制密钥
        byte[] key = {0x7a,0x68,0x67,0x6c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
        byte[]    cipher = Sm4Util.encryptEcb(key, result);//加密后的消息体
        
        byte[] addBytes = addBytes(head, cipher);//合并消息头数据消息体
        int crc2 = CRC16.calcCrc16(addBytes);//CRC校验
        byte[] uint16ToBytes = uint16ToBytes(crc2);
        
        byte[] addAllBytes = addBytes(addBytes, uint16ToBytes);
        
        byte[] index = check7DGetNewArray(addAllBytes);
        byte[] index1 = check7EGetNewArray(index);
        
        byte[] startArray = {0x7E};
        byte[] endArray = {0x7E};
        byte[] endAllBytes = addAllBytes(startArray,index1,endArray);
        return endAllBytes; 
    }
    
    //测试
    public static void main(String[] args) throws Exception {
        //sendSqvMessageBody(90.2323);
        /*byte code =0x1;
        String number ="410122G107QLS00001";
        byte[] registrationPackageMessageBody = getRegistrationPackageMessageBody(0, number);
        System.out.println(registrationPackageMessageBody);*/
        //测试获取注册包
        String number ="410122G107QLS00016";
        for (int i = 0; i < 6; i++) {
            int dowDateNum = getDowDateNum("410122G107QLS00015");
            //System.out.println("累加的流水编号:"+dowDateNum);
        }
        byte[] messageHeader = getMessageHeader(0, number);//消息头
        System.out.println("消息头长度"+messageHeader.length);
        byte[] endAllBytes =getRegistrationPackageAllMessage(messageHeader, 0, number);
        
        /*byte[] endAllBytes = sendHeartbeatPacketMessageBody(2, number);//心跳包
         * */        
        /*byte[] endAllBytes =getAuthenticationPacketMessageBody(1, number);//鉴权包
*/        
        System.out.println("注册包数据长度"+endAllBytes.length);
        ByteConvert.printHexString(endAllBytes);
        
        try
        {
            Socket socket = new Socket("xxxx", xxx);
            //得到一个输出流,用于向服务器发送数据
            OutputStream outputStream = socket.getOutputStream();
                outputStream.write(endAllBytes);
                //刷新缓冲
                outputStream.flush();
                //得到一个输入流,用于接收服务器响应的数据
                InputStream inputStream = socket.getInputStream();
                byte[] bytes = new byte[1]; // 一次读取一个byte
                byte[] bytes1 = new byte[103]; //
                String info = "";
                
                byte[] keyToken=new byte[32];//鉴权码
                
                int state = 0;
                int count = 0;
                byte[] sendSqvMessageBody=null;
                while (true)
                {
                    if (inputStream.available() > 0)
                    {
                        if(state == 0)
                        {
                            inputStream.read(bytes1);
                            String hexStr = ByteArrayToHexStr(bytes);
                            info += HexStrToStr(hexStr);
                            //已经读完
                            if (inputStream.available() == 0)
                            {
                                if(bytes1[1]==0x01){
                                    System.arraycopy(bytes1,2 , keyToken , 0, 32);
                                }
                                ByteConvert.printHexString(keyToken);
                                ByteConvert.printHexString(bytes1);
                                
                                byte[] authenticationPacketMessageBody = getAuthenticationPacketMessageBody(keyToken, 1, number);
                                
                                
                                System.out.println("发送鉴权包");
                                ByteConvert.printHexString(authenticationPacketMessageBody);
                                
                                outputStream.write(authenticationPacketMessageBody);
                                //刷新缓冲
                                outputStream.flush();
                                
                                state =1;
                            }
                            
                        }
                            else if(state ==  1)
                            {
                                System.out.println("鉴权包回复");
                                inputStream.read(bytes1);
                                String hexStr1 = ByteArrayToHexStr(bytes);
                                info += HexStrToStr(hexStr1);
                                ByteConvert.printHexString(bytes1);
                                /*sendSqvMessageBody = sendSqvMessageBody(number, 5.23);//水准仪
*/                                sendSqvMessageBody = sendDvwMessageBoby(number, 10.25);//应变
                                /*sendDvwMessageBoby*/
                                
                                System.out.println("发送水准数据包");
                                ByteConvert.printHexString(sendSqvMessageBody);
                                outputStream.write(sendSqvMessageBody);
                                //刷新缓冲
                                outputStream.flush();
                                
                                outputStream.close();
                                socket.close();
                                state =2;
                                count = 0;
                            }
                            else if(state == 2){
                                
                                System.out.println("数据包回复");
                                inputStream.read(bytes1);
                                String hexStr1 = ByteArrayToHexStr(bytes);
                                info += HexStrToStr(hexStr1);
                                ByteConvert.printHexString(bytes1);
                            }
                        
                    }
                    /*count ++;
                    if(count > 5 && sendSqvMessageBody!=null)
                    {
                        //sendSqvMessageBody = sendSqvMessageBody(number, 5.23);
                         System.out.println("发送水准数据包");
                         ByteConvert.printHexString(sendSqvMessageBody);
                         outputStream.write(sendSqvMessageBody);
                         //刷新缓冲
                         outputStream.flush();
                         count = 0;
                    }*/
                    System.out.println(count);
                    
                }
                
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }


       
        
        
        byte[] str ={0x30,0x7E,0x08,0x7D,0x55};
        
    }
    
    /**
     * CRC校验后返回
     * @param value
     * @return
     */
    public static byte[] uint16ToBytes(int value)
      {
          byte[] src = new byte[2];
          src[0] =  (byte) ((value>>8) & 0xFF);    
          src[1] =  (byte) (value & 0xFF);  
          return src;
      }
    
    static int i=5;
    public  static int getDowDateNum(String number){
        /*Date now = new Date();*/
        i++;
        /*SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd ");//设置日期格式
        String str = df.format(new Date());*/
        //System.out.println(str);
        if(numberMap.isEmpty()){
            numberMap.put(number, i);
        }else{
            numberMap.put(number, i);
        }
        return numberMap.get(number);
    }
    
    public static String getIP()  {
        String ip = "http://pv.sohu.com/cityjson?ie=utf-8";
        String inputLine = "";
        String read = "";
        String toIp="";
        try {
            URL url = new URL(ip);
            HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
            BufferedReader in = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));
            while ((read = in.readLine()) != null) {
                inputLine += read;
            }
            String ObjJson=inputLine.substring(inputLine.indexOf("=")+1,inputLine.length()-1);
            JSONObject jsonObj= JSON.parseObject(ObjJson);
            toIp=jsonObj.getString("cip");
        } catch (Exception e) {
            toIp="";
        }
        return toIp;
    }

    public static byte[] check7EGetNewArray(byte[] mBaseData) {
        int length =0;
        for(int i = 0; i<mBaseData.length;i++){
            if(mBaseData[i]==0x7E){
                length = length+2;
            }else{
                length = length+1;
            }
        }
        byte[] src = new byte[length];
        int j=0;
        for(int i = 0; i<mBaseData.length;i++){
            if(mBaseData[i]==0x7E){
                src[j]=0x7D;
                src[j+1]=0x02;
                j=j+2;
            }else{
                src[j]=mBaseData[i];
                j++;
                
            }
        }
        return src;
    }
    
    public static byte[] check7DGetNewArray(byte[] mBaseData) {
        int length =0;
        for(int i = 0; i<mBaseData.length;i++){
            if(mBaseData[i]==0x7D){
                length = length+2;
            }else{
                length = length+1;
            }
        }
        byte[] src = new byte[length];
        int j=0;
        for(int i = 0; i<mBaseData.length;i++){
            if(mBaseData[i]==0x7D){
                src[j]=0x7D;
                src[j+1]=0x01;
                j=j+2;
            }else{
                src[j]=mBaseData[i];
                j++;
                
            }
        }
        return src;
    }
    /** 
     *  
     * @param data1 
     * @param data2 
     * @return data1 与 data2拼接的结果 
     */  
    public static byte[] addBytes(byte[] data1, byte[] data2) {  
        byte[] data3 = new byte[data1.length + data2.length];  
        System.arraycopy(data1, 0, data3, 0, data1.length);  
        System.arraycopy(data2, 0, data3, data1.length, data2.length);  
        return data3;  
    }  
    
    public static byte[] addAllBytes(byte[] data1, byte[] data2,byte[] data3) {  
        byte[] data4 = new byte[data1.length + data2.length + data3.length];  
        System.arraycopy(data1, 0, data4, 0, data1.length);  
        System.arraycopy(data2, 0, data4, data1.length, data2.length);  
        System.arraycopy(data3, 0, data4, data1.length+data2.length, data3.length);   
        return data4;  
    }  
    
    public static String ByteArrayToHexStr(byte[] byteArray)
    {
        if (byteArray == null)
        {
            return null;
        }
        char[] hexArray = "0123456789ABCDEF".toCharArray();
        char[] hexChars = new char[byteArray.length * 2];
        for (int i = 0; i < byteArray.length; i++)
        {
            int temp = byteArray[i] & 0xFF;
            hexChars[i * 2] = hexArray[temp >>> 4];
            hexChars[i * 2 + 1] = hexArray[temp & 0x0F];
        }
        return new String(hexChars);
    }
 
    /**
     * 16进制的Str转Str
     *
     * @param hexStr
     * @return
     */
    public static String HexStrToStr(String hexStr)
    {
        //能被16整除,肯定可以被2整除
        byte[] array = new byte[hexStr.length() / 2];
        try
        {
            for (int i = 0; i < array.length; i++)
            {
                array[i] = (byte) (0xff & Integer.parseInt(hexStr.substring(i * 2, i * 2 + 2), 16));
            }
            hexStr = new String(array, "UTF-8");
        }
        catch (Exception e)
        {
            e.printStackTrace();
            return "";
        }
        return hexStr;
    }
    
    
    public static void sendData(int flag,String number,double data) throws Exception{
        byte[] messageHeader = getMessageHeader(0, number);//消息头
        byte[] endAllBytes =getRegistrationPackageAllMessage(messageHeader, 0, number);
        /*byte[] endAllBytes = sendHeartbeatPacketMessageBody(2, number);//心跳包
         * */        
        /*byte[] endAllBytes =getAuthenticationPacketMessageBody(1, number);//鉴权包
*/        OutputStream outputStream = null;
        Socket socket = null;
        try
        {
                socket = new Socket("xxxx", xxx);
                //得到一个输出流,用于向服务器发送数据
                 outputStream = socket.getOutputStream();
                outputStream.write(endAllBytes);
                //刷新缓冲
                outputStream.flush();
                //得到一个输入流,用于接收服务器响应的数据
                InputStream inputStream = socket.getInputStream();
                byte[] bytes = new byte[1]; // 一次读取一个byte
                byte[] bytes1 = new byte[103]; //
                String info = "";
                
                byte[] keyToken=new byte[32];//鉴权码
                
                int state = 0;
                int count = 0;
                byte[] sendSqvMessageBody=null;
                while (true)
                {
                    if (inputStream.available() > 0)
                    {
                        if(state == 0)
                        {
                            inputStream.read(bytes1);
                            String hexStr = ByteArrayToHexStr(bytes);
                            info += HexStrToStr(hexStr);
                            //已经读完
                            if (inputStream.available() == 0)
                            {
                                if(bytes1[1]==0x01){
                                    System.arraycopy(bytes1,2 , keyToken , 0, 32);
                                }
                                
                                byte[] authenticationPacketMessageBody = getAuthenticationPacketMessageBody(keyToken, 1, number);
                                outputStream.write(authenticationPacketMessageBody);
                                //刷新缓冲
                                outputStream.flush();
                                
                                state =1;
                            }
                            
                        }
                            else if(state ==  1)
                            {
                                //System.out.println("鉴权包回复");
                                inputStream.read(bytes1);
                                String hexStr1 = ByteArrayToHexStr(bytes);
                                info += HexStrToStr(hexStr1);
                                //ByteConvert.printHexString(bytes1);
                                if(flag == 2){
                                    sendSqvMessageBody = sendDvwMessageBoby(number, data);//应变
                                }else{
                                    sendSqvMessageBody = sendSqvMessageBody(number, data);//水准仪
                                }
                                outputStream.write(sendSqvMessageBody);
                                //刷新缓冲
                                outputStream.flush();
                               
                                state =2;
                                count = 0;
                                outputStream.close();
                                socket.close();
                            }
                            else if(state == 2){
                                /*System.out.println("数据包回复");
                                inputStream.read(bytes1);
                                String hexStr1 = ByteArrayToHexStr(bytes);
                                info += HexStrToStr(hexStr1);
                                ByteConvert.printHexString(bytes1);*/
                            }
                    }
                }
                
        }
        catch (IOException e)
        {
            e.printStackTrace();
            outputStream.close();
            socket.close();
        }
    }
                

}

package TCPserver;

public class CRC16 {
    static byte[] crc16_tab_h = { (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x01, (byte) 0xC0,  
            (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1,  
            (byte) 0x81, (byte) 0x40, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0,  
            (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0,  
            (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40 };  
  
    static byte[] crc16_tab_l = { (byte) 0x00, (byte) 0xC0, (byte) 0xC1, (byte) 0x01, (byte) 0xC3, (byte) 0x03, (byte) 0x02, (byte) 0xC2, (byte) 0xC6, (byte) 0x06, (byte) 0x07, (byte) 0xC7, (byte) 0x05, (byte) 0xC5, (byte) 0xC4, (byte) 0x04, (byte) 0xCC, (byte) 0x0C, (byte) 0x0D, (byte) 0xCD, (byte) 0x0F, (byte) 0xCF, (byte) 0xCE, (byte) 0x0E, (byte) 0x0A, (byte) 0xCA, (byte) 0xCB, (byte) 0x0B, (byte) 0xC9, (byte) 0x09, (byte) 0x08, (byte) 0xC8, (byte) 0xD8, (byte) 0x18, (byte) 0x19, (byte) 0xD9, (byte) 0x1B, (byte) 0xDB, (byte) 0xDA, (byte) 0x1A, (byte) 0x1E, (byte) 0xDE, (byte) 0xDF, (byte) 0x1F, (byte) 0xDD, (byte) 0x1D, (byte) 0x1C, (byte) 0xDC, (byte) 0x14, (byte) 0xD4, (byte) 0xD5, (byte) 0x15, (byte) 0xD7, (byte) 0x17, (byte) 0x16, (byte) 0xD6, (byte) 0xD2, (byte) 0x12,  
            (byte) 0x13, (byte) 0xD3, (byte) 0x11, (byte) 0xD1, (byte) 0xD0, (byte) 0x10, (byte) 0xF0, (byte) 0x30, (byte) 0x31, (byte) 0xF1, (byte) 0x33, (byte) 0xF3, (byte) 0xF2, (byte) 0x32, (byte) 0x36, (byte) 0xF6, (byte) 0xF7, (byte) 0x37, (byte) 0xF5, (byte) 0x35, (byte) 0x34, (byte) 0xF4, (byte) 0x3C, (byte) 0xFC, (byte) 0xFD, (byte) 0x3D, (byte) 0xFF, (byte) 0x3F, (byte) 0x3E, (byte) 0xFE, (byte) 0xFA, (byte) 0x3A, (byte) 0x3B, (byte) 0xFB, (byte) 0x39, (byte) 0xF9, (byte) 0xF8, (byte) 0x38, (byte) 0x28, (byte) 0xE8, (byte) 0xE9, (byte) 0x29, (byte) 0xEB, (byte) 0x2B, (byte) 0x2A, (byte) 0xEA, (byte) 0xEE, (byte) 0x2E, (byte) 0x2F, (byte) 0xEF, (byte) 0x2D, (byte) 0xED, (byte) 0xEC, (byte) 0x2C, (byte) 0xE4, (byte) 0x24, (byte) 0x25, (byte) 0xE5, (byte) 0x27, (byte) 0xE7,  
            (byte) 0xE6, (byte) 0x26, (byte) 0x22, (byte) 0xE2, (byte) 0xE3, (byte) 0x23, (byte) 0xE1, (byte) 0x21, (byte) 0x20, (byte) 0xE0, (byte) 0xA0, (byte) 0x60, (byte) 0x61, (byte) 0xA1, (byte) 0x63, (byte) 0xA3, (byte) 0xA2, (byte) 0x62, (byte) 0x66, (byte) 0xA6, (byte) 0xA7, (byte) 0x67, (byte) 0xA5, (byte) 0x65, (byte) 0x64, (byte) 0xA4, (byte) 0x6C, (byte) 0xAC, (byte) 0xAD, (byte) 0x6D, (byte) 0xAF, (byte) 0x6F, (byte) 0x6E, (byte) 0xAE, (byte) 0xAA, (byte) 0x6A, (byte) 0x6B, (byte) 0xAB, (byte) 0x69, (byte) 0xA9, (byte) 0xA8, (byte) 0x68, (byte) 0x78, (byte) 0xB8, (byte) 0xB9, (byte) 0x79, (byte) 0xBB, (byte) 0x7B, (byte) 0x7A, (byte) 0xBA, (byte) 0xBE, (byte) 0x7E, (byte) 0x7F, (byte) 0xBF, (byte) 0x7D, (byte) 0xBD, (byte) 0xBC, (byte) 0x7C, (byte) 0xB4, (byte) 0x74,  
            (byte) 0x75, (byte) 0xB5, (byte) 0x77, (byte) 0xB7, (byte) 0xB6, (byte) 0x76, (byte) 0x72, (byte) 0xB2, (byte) 0xB3, (byte) 0x73, (byte) 0xB1, (byte) 0x71, (byte) 0x70, (byte) 0xB0, (byte) 0x50, (byte) 0x90, (byte) 0x91, (byte) 0x51, (byte) 0x93, (byte) 0x53, (byte) 0x52, (byte) 0x92, (byte) 0x96, (byte) 0x56, (byte) 0x57, (byte) 0x97, (byte) 0x55, (byte) 0x95, (byte) 0x94, (byte) 0x54, (byte) 0x9C, (byte) 0x5C, (byte) 0x5D, (byte) 0x9D, (byte) 0x5F, (byte) 0x9F, (byte) 0x9E, (byte) 0x5E, (byte) 0x5A, (byte) 0x9A, (byte) 0x9B, (byte) 0x5B, (byte) 0x99, (byte) 0x59, (byte) 0x58, (byte) 0x98, (byte) 0x88, (byte) 0x48, (byte) 0x49, (byte) 0x89, (byte) 0x4B, (byte) 0x8B, (byte) 0x8A, (byte) 0x4A, (byte) 0x4E, (byte) 0x8E, (byte) 0x8F, (byte) 0x4F, (byte) 0x8D, (byte) 0x4D,  
            (byte) 0x4C, (byte) 0x8C, (byte) 0x44, (byte) 0x84, (byte) 0x85, (byte) 0x45, (byte) 0x87, (byte) 0x47, (byte) 0x46, (byte) 0x86, (byte) 0x82, (byte) 0x42, (byte) 0x43, (byte) 0x83, (byte) 0x41, (byte) 0x81, (byte) 0x80, (byte) 0x40 };  
  
    /** 
     * 计算CRC16校验 
     *  
     * @param data 
     *            需要计算的数组 
     * @return CRC16校验值 
     */  
    public static int calcCrc16(byte[] data) {  
        return calcCrc16(data, 0, data.length);  
    }  
  
    /** 
     * 计算CRC16校验 
     *  
     * @param data 
     *            需要计算的数组 
     * @param offset 
     *            起始位置 
     * @param len 
     *            长度 
     * @return CRC16校验值 
     */  
    public static int calcCrc16(byte[] data, int offset, int len) {  
        return calcCrc16(data, offset, len, 0xffff);  
    }  
  
    /** 
     * 计算CRC16校验 
     *  
     * @param data 
     *            需要计算的数组 
     * @param offset 
     *            起始位置 
     * @param len 
     *            长度 
     * @param preval 
     *            之前的校验值 
     * @return CRC16校验值 
     */  
    public static int calcCrc16(byte[] data, int offset, int len, int preval) {  
        int ucCRCHi = (preval & 0xff00) >> 8;  
        int ucCRCLo = preval & 0x00ff;  
        int iIndex;  
        for (int i = 0; i < len; ++i) {  
            iIndex = (ucCRCLo ^ data[offset + i]) & 0x00ff;  
            ucCRCLo = ucCRCHi ^ crc16_tab_h[iIndex];  
            ucCRCHi = crc16_tab_l[iIndex];  
        }  
        return ((ucCRCHi & 0x00ff) << 8) | (ucCRCLo & 0x00ff) & 0xffff;  
    }  

}


SM4加密

package com.AIOT.utils;

import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.SecureRandom;
import java.security.Security;
import java.util.Arrays;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.spec.SecretKeySpec;

import org.bouncycastle.jce.provider.BouncyCastleProvider;

import TCPserver.SocketUtil;
/**
 * sm4加密算法工具类
 * @explain sm4加密、解密与加密结果验证
 *          可逆算法
 */
public class Sm4Util {
 
    static {
        Security.addProvider(new BouncyCastleProvider());
    }
 
    private static final String ENCODING = "UTF-8";
    public static final String ALGORITHM_NAME = "SM4";
    // 加密算法/分组加密模式/分组填充方式
    // PKCS5Padding-以8个字节为一组进行分组加密
    // 定义分组加密模式使用:PKCS5Padding
    public static final String ALGORITHM_NAME_ECB_PADDING = "SM4/ECB/PKCS5Padding";
    // 128-32位16进制;256-64位16进制
    public static final int DEFAULT_KEY_SIZE = 128;
    
    /**
     * 生成ECB暗号
     * @explain ECB模式(电子密码本模式:Electronic codebook)
     * @param algorithmName
     *            算法名称
     * @param mode
     *            模式
     * @param key
     * @return
     * @throws Exception
     */
    private static Cipher generateEcbCipher(String algorithmName, int mode, byte[] key) throws Exception {
        Cipher cipher = Cipher.getInstance(algorithmName, BouncyCastleProvider.PROVIDER_NAME);
        Key sm4Key = new SecretKeySpec(key, ALGORITHM_NAME);
        cipher.init(mode, sm4Key);
        return cipher;
    }
    
    /**
     * 自动生成密钥
     * @explain
     * @return
     * @throws NoSuchAlgorithmException
     * @throws NoSuchProviderException
     */
    public static byte[] generateKey() throws Exception {
        return generateKey(DEFAULT_KEY_SIZE);
    }
     
    /**
     * @explain
     * @param keySize
     * @return
     * @throws Exception
     */
    public static byte[] generateKey(int keySize) throws Exception {
        KeyGenerator kg = KeyGenerator.getInstance(ALGORITHM_NAME, BouncyCastleProvider.PROVIDER_NAME);
        kg.init(keySize, new SecureRandom());
        return kg.generateKey().getEncoded();
    }
    
    /**
     * sm4加密
     * @explain 加密模式:ECB
     *          密文长度不固定,会随着被加密字符串长度的变化而变化
     * @param hexKey
     *            16进制密钥(忽略大小写)
     * @param paramStr
     *            待加密字符串
     * @return 返回16进制的加密字符串
     * @throws Exception
     */
    public static byte[] encryptEcb(byte[] keyData, byte[] srcData) throws Exception {
        //String cipherText = "";
        // String-->byte[]
        //byte[] srcData = paramStr.getBytes(ENCODING);
        // 加密后的数组
        byte[] cipherArray = encrypt_Ecb_Padding(keyData, srcData);
        // byte[]-->hexString
        //cipherText = ByteUtils.toHexString(cipherArray);
        return cipherArray;
    }
     
    /**
     * 加密模式之Ecb
     * @explain
     * @param key
     * @param data
     * @return
     * @throws Exception
     */
    public static byte[] encrypt_Ecb_Padding(byte[] key, byte[] data) throws Exception {
        Cipher cipher = generateEcbCipher(ALGORITHM_NAME_ECB_PADDING, Cipher.ENCRYPT_MODE, key);
        return cipher.doFinal(data);
    }
    
    /**
     * sm4解密
     * @explain 解密模式:采用ECB
     * @param hexKey
     *            16进制密钥
     * @param cipherText
     *            16进制的加密字符串(忽略大小写)
     * @return 解密后的字符串
     * @throws Exception
     */
    public static byte[] decryptEcb(byte[] keyData, byte[] cipherData) throws Exception {
        // hexString-->byte[]
        //byte[] cipherData = ByteUtils.fromHexString(cipherText);
        // 解密
        byte[] srcData = decrypt_Ecb_Padding(keyData, cipherData);
        // byte[]-->String
        return srcData;
    }
        
    /**
     * 解密
     * @explain
     * @param key
     * @param cipherText
     * @return
     * @throws Exception
     */
    public static byte[] decrypt_Ecb_Padding(byte[] key, byte[] cipherText) throws Exception {
        Cipher cipher = generateEcbCipher(ALGORITHM_NAME_ECB_PADDING, Cipher.DECRYPT_MODE, key);
        return cipher.doFinal(cipherText);
    }
    
    /**
     * 校验加密前后的字符串是否为同一数据
     * @explain
     * @param hexKey
     *            16进制密钥(忽略大小写)
     * @param cipherText
     *            16进制加密后的字符串
     * @param paramStr
     *            加密前的字符串
     * @return 是否为同一数据
     * @throws Exception
     */
    public static boolean verifyEcb(byte[] keyData, byte[] cipherData, byte[] srcData) throws Exception {
        // 用于接收校验结果
        boolean flag = false;
        // 将16进制字符串转换成数组
        //byte[] cipherData = ByteUtils.fromHexString(cipherText);
        // 解密
        byte[] decryptData = decrypt_Ecb_Padding(keyData, cipherData);
        // 将原字符串转换成byte[]
        //byte[] srcData = paramStr.getBytes(ENCODING);
        // 判断2个数组是否一致
        flag = Arrays.equals(decryptData, srcData);
        return flag;
    }
    
   /* public static void main(String[] args) {
        try {
            String json = "{\"name\":\"Marydon\",\"website\":\"http://www.cnblogs.com/Marydon20170307\"}";
            // 自定义的32位16进制密钥
            byte[] key = {0x7a,0x68,0x67,0x6c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
            byte[] cipher = Sm4Util.encryptEcb(key, json.getBytes());
            System.out.println(cipher);//b0a27fa6826a3158183ca52b4ea35c00a0ff24f0a9d1b8b42e439f00ffca11dee4dbcf598ba0a40a2ffbb0890b16be33dd61392841e77ff907fef7d68b930bac4ada2aacd85b6926fa3260a73f346a6b
            System.out.println(Sm4Util.verifyEcb(key, cipher, json.getBytes()));// true
            json = Sm4Util.decryptEcb(key, cipher);
            System.out.println(json);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }*/
    
    public static void main(String[] args) {
    	byte[] data1 = new byte[]{0x11,0x22};
    	byte[] data2 = new byte[]{0x00,0x00};
    	byte[] data3 = new byte[]{0x33,0x44};
    	byte[] addAllBytes = SocketUtil.addAllBytes(data1, data2, data3);
    	System.out.println(addAllBytes.length);
	}
    
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值