go语言8583协议报文解析类封装

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq8864/article/details/86313728

工作中用到了,想在电脑上跑交易,做个工具。用c语音处理起来效率不高。

于是用go语言做一个8583解析类,方便使用 

https://github.com/yangyongzhen/go8583/

/**
 * Created by yangyongzhen on 2019/01/11
 * simple 8583 Protocol Analysis
 */

package easy8583

import (
	"bytes"
	"fmt"
	"strconv"
)

type Field struct {
	Ihave bool   //是否存在该域
	Ltype int    //长度类型 (NOVAR,LLVAR,LLLVAR)
	Dtype int    //数据类型 (BCD,ASCII)
	Len   int    //域的数据内容的长度
	Data  []byte //域的有效数据
}

type Easy8583 struct {
	Len     []byte
	Tpdu    []byte
	Head    []byte
	Msgtype []byte
	Bitmap  []byte

	Txbuf   []byte

	Field_S []Field //发送的域
	Field_R []Field //接收的域
}

//定义枚举类型 长度类型定义
const (
	NOVAR  = iota //value = 0,定长,
	LLVAR         //value = 1,长度为1字节
	LLLVAR        //value = 2,长度为2字节

)

//定义枚举类型 数据类型定义
const (
	UN  = iota //value = 0, 未定义,定长的域无需关注类型
	BIN        //value = 1,BIN
	BCD        //value = 2,BCD
)

//各个域的初始配置
func (ea *Easy8583) Init8583Fields(fds []Field) {

	 for i := 0; i < 64;i++ {
	 	fds[i].Ihave = false
	 }

	fds[0].Ltype = 0

	fds[1].Ltype = LLVAR //LLVAR
	fds[1].Dtype = BCD

	fds[2].Ltype = 0
	fds[2].Len = 3

	fds[3].Ltype = 0
	fds[3].Len = 6

	fds[10].Ltype = 0
	fds[10].Len = 3

	fds[11].Ltype = 0
	fds[11].Len = 3

	fds[12].Ltype = 0
	fds[12].Len = 2

	fds[13].Ltype = 0
	fds[13].Len = 2
	fds[14].Ltype = 0
	fds[14].Len = 2

	fds[21].Ltype = 0
	fds[21].Len = 2
	fds[22].Ltype = 0
	fds[22].Len = 2

	fds[24].Ltype = 0
	fds[24].Len = 1
	fds[25].Ltype = 0
	fds[25].Len = 1

	fds[31].Ltype = LLVAR //LLVAR
	fds[31].Dtype = BCD
	fds[34].Ltype = LLVAR //LLVAR
	fds[34].Dtype = BCD

	fds[36].Ltype = 0
	fds[36].Len = 12

	fds[37].Ltype = 0
	fds[37].Len = 6
	fds[38].Ltype = 0
	fds[38].Len = 2

	fds[39].Ltype = LLVAR

	fds[40].Ltype = 0
	fds[40].Len = 8
	fds[41].Ltype = 0
	fds[41].Len = 15

	fds[43].Ltype = LLVAR

	fds[47].Ltype = LLLVAR
	fds[47].Dtype = BCD

	fds[48].Ltype = 0
	fds[48].Len = 3
	fds[51].Ltype = 0
	fds[51].Len = 8
	fds[52].Ltype = 0
	fds[52].Len = 8

	fds[54].Ltype = LLLVAR //LLLVAR
	fds[58].Ltype = LLLVAR

	fds[59].Ltype = LLLVAR
	fds[59].Dtype = BCD

	fds[60].Ltype = LLLVAR
	fds[60].Dtype = BCD

	fds[61].Ltype = LLLVAR
	fds[62].Ltype = LLLVAR

	fds[63].Ltype = 0
	fds[63].Len = 8

}

/*
构造函数,初始化
*/

func New8583() *Easy8583 {

	var ea = new(Easy8583)
	ea.Txbuf = make([]byte, 0, 1024)
	ea.Txbuf = ea.Txbuf[0:23]

	ea.Len  = []byte{0x00, 0x00}
	ea.Tpdu = []byte{0x60, 0x05, 0x01, 0x00, 0x00}
	ea.Head = []byte{0x61, 0x31, 0x00, 0x31, 0x11, 0x08}

	ea.Msgtype = []byte{0x08, 0x00}

	ea.Bitmap = make([]byte, 8)

	ea.Field_S = make([]Field,64)
	ea.Field_R = make([]Field,64)

	ea.Init8583Fields(ea.Field_S)
	ea.Init8583Fields(ea.Field_R)


	return ea
}

func memcpy(dst, src []byte, size int) {
	for i := 0; i < size; i++ {
		dst[i] = src[i]
	}
	return
}

func bytesToHexStr(data []byte, lenth int) string {
	buf := data[0:lenth]
	hexStr := fmt.Sprintf("%x", buf)
	//fmt.Println(hexStr)
	return hexStr

}

// bytes to hex string
func bytesToHexString(b []byte) string {
	var buf bytes.Buffer
	for _, v := range b {
		t := strconv.FormatInt(int64(v), 16)
		if len(t) > 1 {
			buf.WriteString(t)
		} else {
			buf.WriteString("0" + t)
		}
	}
	return buf.String()
}

// hex string to bytes
func hexStringToBytes(s string) []byte {
	bs := make([]byte, 0)
	for i := 0; i < len(s); i = i + 2 {
		b, _ := strconv.ParseInt(s[i:i+2], 16, 16)
		bs = append(bs, byte(b))
	}
	return bs
}

//例:0x19 --> 19, 0x0119 -> 119
func bcdToInt(data []byte, lenth int) int {
	buf := data[0:lenth]
	hexStr := fmt.Sprintf("%x", buf)
	out, _ := strconv.ParseInt(hexStr, 10, 32)
	return int(out)

}
func toZero(p []byte) {
	for i := range p {
		p[i] = 0
	}
}

/*
8583报文打包
*/
func (ea *Easy8583) Pack8583Fields() int {
	fmt.Printf("pack 8583 fields\n")
	//ea.Txbuf[]
	ea.Txbuf = ea.Txbuf[0:23]
	toZero(ea.Txbuf)

	memcpy(ea.Txbuf[2:], ea.Tpdu, 5)
	memcpy(ea.Txbuf[7:], ea.Head, 6)
	memcpy(ea.Txbuf[13:], ea.Msgtype, 2)
	memcpy(ea.Txbuf[15:], ea.Bitmap, 8)

	j := 0
	len := 23
	tmplen := 0
	seat := 0x80
	for i := 0; i < 64; i++ {
		seat = (seat >> 1)
		if (i % 8) == 0 {
			j++
			seat = 0x80
		}
		if ea.Field_S[i].Ihave {
			ea.Bitmap[j-1] |= byte(seat)
			if ea.Field_S[i].Ltype == NOVAR {
				ea.Txbuf = ea.Txbuf[0 : len+ea.Field_S[i].Len]
				memcpy(ea.Txbuf[len:], ea.Field_S[i].Data, ea.Field_S[i].Len)
				len += ea.Field_S[i].Len

			} else if ea.Field_S[i].Ltype == LLVAR {
				ea.Txbuf = ea.Txbuf[0 : len+1]
				ea.Txbuf[len] = byte(ea.Field_S[i].Len)

				tmplen = bcdToInt(ea.Txbuf[len:],1)
				if ea.Field_S[i].Dtype == BCD {
					tmplen = ((tmplen/2) + (tmplen%2))
				}
				len += 1
				ea.Txbuf = ea.Txbuf[0 : len+tmplen]
				memcpy(ea.Txbuf[len:], ea.Field_S[i].Data, tmplen)
				len += tmplen

			} else if ea.Field_S[i].Ltype == LLLVAR {
				ea.Txbuf = ea.Txbuf[0 : len+2]
				ea.Txbuf[len] =   byte(ea.Field_S[i].Len>>8)
				ea.Txbuf[len+1] = byte(ea.Field_S[i].Len)

				tmplen = bcdToInt(ea.Txbuf[len:],2)
				if ea.Field_S[i].Dtype == BCD {
					tmplen = ((tmplen/2) + (tmplen%2))
				}
				len += 2
				ea.Txbuf = ea.Txbuf[0 : len+tmplen]
				memcpy(ea.Txbuf[len:], ea.Field_S[i].Data, tmplen)
				len += tmplen

			}

		}
		//报文总长度
		ea.Txbuf[0] = byte((len-2)>>8)
		ea.Txbuf[1] = byte((len-2))
		memcpy(ea.Len,ea.Txbuf,2)

	}

	return 0
}


/*
8583报文解包
*/
func (ea *Easy8583) Ans8583Fields( rxbuf []byte,rxlen int) int {
	fmt.Printf("ans 8583 fields\n")
	ea.Init8583Fields(ea.Field_R)

	len := 0
	tmplen := 0
	bitMap := make([]byte,8)
	var seat,buf uint64 = 1,0

	memcpy(bitMap,rxbuf[15:],8)

	memcpy(ea.Len,rxbuf[0:],2)
	//memcpy(ea.Tpdu,rxbuf[2:],5)
	memcpy(ea.Head,rxbuf[7:],6)
	memcpy(ea.Msgtype,rxbuf[13:],2)
	memcpy(ea.Bitmap,rxbuf[15:],8)

	len += 23

	for i := 0;i < 8;i++ {
        buf = ((buf<<8) | uint64(bitMap[i]))
	}

	for i := 0; i < 64; i++ {
		if  (buf & (seat << uint(63 - i))) > 0 {
			ea.Field_R[i].Ihave = true
			if ea.Field_R[i].Ltype == NOVAR {
				ea.Field_R[i].Data = make([]byte,ea.Field_R[i].Len)
				memcpy(ea.Field_R[i].Data, rxbuf[len:], ea.Field_R[i].Len)
				len += ea.Field_R[i].Len

			} else if ea.Field_R[i].Ltype == LLVAR {
			
				ea.Field_R[i].Len = int(rxbuf[len])

				tmplen = bcdToInt(rxbuf[len:],1)
				if ea.Field_R[i].Dtype == BCD {
					tmplen = ((tmplen/2) + (tmplen%2))
				}
				len += 1
				ea.Field_R[i].Data = make([]byte,tmplen)
				memcpy(ea.Field_R[i].Data, rxbuf[len:], tmplen)
				len += tmplen

			} else if ea.Field_R[i].Ltype == LLLVAR {

				ea.Field_R[i].Len = ( ( int(rxbuf[len])<<8 ) | int(rxbuf[len+1] ) )

				tmplen = bcdToInt(rxbuf[len:],2)
				if ea.Field_R[i].Dtype == BCD {
					tmplen = ((tmplen/2) + (tmplen%2))
				}
				len += 2
				ea.Field_R[i].Data = make([]byte,tmplen)
				memcpy(ea.Field_R[i].Data, rxbuf[len:], tmplen)
				len += tmplen

			}

		}

	}

	if(len > rxlen){
        return 1;
	}
	
	return 0
}

/*
打印信息,调试用
*/
func (ea *Easy8583) PrintFields(fds []Field){
	fmt.Println("Print fields...")
	fmt.Printf("\n==========================================\n")
	fmt.Printf("Len:\t%s\n", bytesToHexString(ea.Len))
	fmt.Printf("Tpdu:\t%s\n", bytesToHexString(ea.Tpdu))
	fmt.Printf("Head:\t%s\n", bytesToHexString(ea.Head))
	fmt.Printf("Msge:\t%s\n", bytesToHexString(ea.Msgtype))
	fmt.Printf("Bitmap:\t%s\n", bytesToHexString(ea.Bitmap))
	fmt.Printf("\n==========================================\n")
	for i:=0; i < 64; i++{
		if fds[i].Ihave {
			fmt.Printf("[field:%d] ",i+1)
			if fds[i].Ltype == LLVAR{
				fmt.Printf("[len:%02x] ",fds[i].Len)
			}else if fds[i].Ltype == LLLVAR{
				fmt.Printf("[len:%04x] ",fds[i].Len)
			}
			
			fmt.Printf("[%s]\n",bytesToHexString(fds[i].Data))
			fmt.Printf("\n------------------------------\n")
		
		}
	}
}

func main() {

	fmt.Println("test...")
}

猜你喜欢

转载自blog.csdn.net/qq8864/article/details/86313728
今日推荐