goLang 实现根据帧头帧尾截取数据 备忘

/*
	1.此类想做成数据缓冲区的功能能,能够接受网络包进行数据缓冲区,根据
	2. 根据帧头帧尾去能够完成数据截取,老的思路是去掉没有用的数据把数据都一个一个移位
	3. 功能测试  目前功能正常
*/

package queue

import (
	"sync"
)

type queue struct {
	head   int
	foot   int
	arr    []byte
	mutexP *sync.Mutex

	headArr      []byte
	footArr      []byte
	realDataChan chan []byte
}

//创建一个数据缓冲区
func CreateQueue(len int, headBytes, footBytes []byte) queue {
	qu := queue{
		head:         0, //包含此下标值
		foot:         0, // 不包含此下标值
		mutexP:       &sync.Mutex{},
		arr:          make([]byte, len+1),
		realDataChan: make(chan []byte, 5),
	}
	qu.footArr = append(qu.footArr, footBytes...)
	qu.headArr = append(qu.headArr, headBytes...)
	return qu
}

//入队
func (its *queue) enqueue(v byte) bool {

	if (its.foot+1)%len(its.arr) == its.head {
		return false
	}
	its.arr[its.foot] = v
	its.foot = (its.foot + 1) % len(its.arr)
	return true
}

//出队
func (its *queue) dequeue() (val byte, bl bool) {
	val = 0
	bl = false
	if its.foot == its.head {
		return
	}
	val = its.arr[its.head]
	its.head = (its.head + 1) % len(its.arr)
	bl = true
	return
}

//计算长度
func (its *queue) Count() int {
	dataLen := (its.foot + len(its.arr) - its.head) % len(its.arr)
	return dataLen
}

//判断队列是否存储满了
func (its *queue) IsFull() bool {
	its.mutexP.Lock()
	defer its.mutexP.Unlock()
	return its.foot == its.head
}

//判断队列是否为空
func (its *queue) IsEmpty() bool {
	its.mutexP.Lock()
	defer its.mutexP.Unlock()
	return (its.foot+1)%len(its.arr) == its.head
}

//获取当前缓冲区全部信息
func (its *queue) GetCurArrInfo() []byte {
	its.mutexP.Lock()
	defer its.mutexP.Unlock()
	arrLen := len(its.arr)
	lens := (its.foot + arrLen - its.head) % arrLen
	splice := make([]byte, lens)
	if lens == 0 {
		return splice
	}
	//数组不为空则去添加数据
	tempHead := its.head
	for idx := 0; idx < lens; idx++ {
		tempHead = (its.head + idx) % arrLen
		splice[idx] = its.arr[tempHead]
	}
	return splice
}

//清空队列
func (its *queue) Clear() {
	its.mutexP.Lock()
	defer its.mutexP.Unlock()
	for idx := 0; idx < len(its.arr); idx++ {
		its.arr[idx] = 0
	}
	its.head = 0
	its.foot = 0
}

//获取队列容量
func (its *queue) Capacity() int {
	its.mutexP.Lock()
	defer its.mutexP.Unlock()
	return len(its.arr) - 1
}

//返回所有结果集的切片
func (its *queue) GetResult() [][]byte {
	var reault [][]byte

	for {
		if len(its.realDataChan) > 0 {
			reault = append(reault, <-its.realDataChan)
		} else {
			break
		}
	}
	return reault
}

//添加一个数据包到缓冲区 并且根据帧头帧尾截取数据  若果缓冲区满了或者结果chan满了则不能再次加入
func (this *queue) AddBuf(buf []byte) bool {
	if buf == nil || len(buf) == 0 {
		return false
	}
	//1. 判断数据是否能够存下数据
	this.mutexP.Lock()
	defer this.mutexP.Unlock()
	for idx := 1; idx <= len(buf); idx++ {
		if (this.foot+1+idx)%len(this.arr) == this.foot {
			return false
		}
	}
	// 1.1 程序结果缓冲区 是否已经满了
	if len(this.realDataChan) == cap(this.realDataChan) {
		return false
	}

	//2.存入数据
	for _, v := range buf {
		this.enqueue(v)
	}

	//3. 判断数据是否符合要求
	for {
		headNu := this.findHeadOrFoot(1)
		count := this.Count()
		if headNu == -1 {
			//1. 此时没有找到指定头数据
			arrLength := len(this.headArr)
			if count >= arrLength {
				for dquI := 0; dquI < count-arrLength; dquI++ {
					this.dequeue()
				}
			}
			break
		} else {
			//2. 此种情况找到了有效头位置
			if count > len(this.headArr)+len(this.footArr) {
				//2.1 开始找帧尾数据 前去除帧头无效数据
				var deletNu = (headNu + len(this.arr) - this.head) % len(this.arr)
				for i := 0; i < deletNu; i++ {
					this.dequeue()
				}
				footNu := this.findHeadOrFoot(2)
				if footNu != -1 {
					//2.2 此种情况找到了帧尾
					entity := make([]byte, (footNu+len(this.footArr)+len(this.arr)-this.head)%len(this.arr))
					var tempByte byte
					var tempDequBl bool
					for inx := 0; inx < cap(entity); inx++ {
						tempByte, tempDequBl = this.dequeue()

						if tempDequBl {
							entity[inx] = tempByte
						}
					}
					this.realDataChan <- entity

				} else {
					break
				}
			}
		}
	}
	return true
}

// 查找帧头和帧尾  1头 2尾
// 如果返回-1 则表示无效
func (its *queue) findHeadOrFoot(headOrfoot byte) int {
	headNu := -1
	if !(headOrfoot == 1 || headOrfoot == 2) {
		return headNu
	}
	arrLen := len(its.arr)
	lens := (its.foot + arrLen - its.head) % arrLen
	if lens == 0 {
		return headNu
	}
	//1. 开始遍历切片缓冲区
	tempHead := its.head //为了查找数据用的
	var (
		corDataLen int
		corDataBuf []byte
	)
	if headOrfoot == 1 {
		corDataLen = len(its.headArr)
		corDataBuf = its.headArr
	} else if headOrfoot == 2 {
		corDataLen = len(its.footArr)
		corDataBuf = its.footArr
	}
	var headJ int = 0
	for idx := 0; idx < lens; idx++ {
		tempHead = (its.head + idx) % arrLen
		//2. 开始对比帧数据
		for headJ = 0; headJ < corDataLen; headJ++ {
			if its.arr[(tempHead+headJ)%arrLen] != corDataBuf[headJ] {
				break
			}
		}
		if corDataLen == headJ {
			headNu = tempHead
			//3. 找到第一个符合要求返回 开始位置
			break
		}
	}
	return headNu
}

也可以用其他语言实现此功能,在处理数据需要拼数据包 感觉更好用一些, 但是在add函数中感觉 功能却有点混乱

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

望天hous

你的鼓励是我最大动力~谢谢啦!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值