/*
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函数中感觉 功能却有点混乱