每个数据包写入ringbuffer的存储结构:
packet_size:uint16 | packet_ctx:byte[ ]
整个ringbuffer的结构:
----------<——start:读的位置
packet1
----------
packet2
--------<——start+use:写的位置
……
type Ringbuffer struct{
start,use int
buf []byte
}
ringbuffer中buf为存储数据内容,start为读的位置的index,use为ringbuffer中未读数据包的字节数,start+
use便是写的位置。
实现要点一:绕回
ringbuffer是一个环,写入到尾部之后需要绕回到尾部,由于数据包是不定大小,所以到了尾部可能会出现数
据包一半在尾部一半在开头,对应的读取的时候数据包一半在尾部,一半在开头需要把它们合并起来。
实现要点二:写入过快,释放覆盖
当写入速度大于读取速度时,新写入数据会与未读数据发生覆盖,这样就有两种决策:覆盖未读数据和丢弃新
写入数据。
实现要点三:避免重复读取
由于ringbuffer是通过覆盖写入数据,并不会删除未读数据,所以就通过ringbuffer中的use来判断是否还有未读
数据。
package ringbuffer
import(
"fmt"
)
type Ringbuffer struct{
start,use int
buf []byte
}
func IntToByte(n int) []byte{
buf:=make([]byte,4)
buf[3] = (byte)((n>>24) & 0xFF)
buf[2] = (byte)((n>>16) & 0xFF)
buf[1] = (byte)((n>>8) & 0xFF)
buf[0] = (byte)(n & 0xFF);
return buf
}
func ByteToInt(buf []byte) int{
var value int
value = (int)((buf[0] & 0xFF)|((buf[1] & 0xFF)<<8)|((buf[2] & 0xFF)<<16)|((buf[3] & 0xFF)<<24))
return value;
}
func NewRingbuffer(size int) *Ringbuffer{
return &Ringbuffer{0,0,make([]byte,size)}
}//覆盖未读数据包策略
func (r *Ringbuffer) WriteCover(b []byte) bool {
block_size:=len(b)
if block_size > 0 {
size:=len(r.buf)
start:=(r.start+r.use)%size
size_byte:= IntToByte(block_size)
/*判断是非会覆盖未读block,
是的话,修改r.start */
flag:=block_size+len(size_byte)
for flag > (r.start-start+size)%size &&r.use!=0 {
rblock_size:= ByteToInt(r.buf[r.start:r.start+4])
r.start = (r.start + rblock_size + 4)%size
}
//保存block的长度
n:=copy(r.buf[start:],size_byte)
if start+len(size_byte) > len(r.buf){
copy(r.buf,size_byte[n:])//判断是否需要绕回
}
start = (start+len(size_byte))%size
//保存block的内容
n =copy(r.buf[start:],b)
if start+len(b) > len(r.buf){
copy(r.buf,b[n:])//判断是非需要绕回
}
start = (start+block_size)%size
//更新ringbuffer的使用量
r.use = (start+size-r.start)%size
return true
}
return false
}//丢弃新写入策略
func (r *Ringbuffer) Write(b []byte) bool {
block_size:=len(b)
if block_size > 0 {
size:=len(r.buf)
start:=(r.start+r.use)%size
size_byte:= IntToByte(block_size)
//判断ringbuffer是否还有空间存放block
end:=(start+len(b)+len(size_byte))
flag:=end-len(r.buf)
if flag>0 && flag > r.start {
return false
}
//保存block的长度
n:=copy(r.buf[start:],size_byte)
if start+len(size_byte) > len(r.buf){
copy(r.buf,size_byte[n:])
}
start = (start+len(size_byte))%size
//保存block的内容
n =copy(r.buf[start:],b)
if start+len(b) > len(r.buf){
copy(r.buf,b[n:])
}
start = (start+block_size)%size
//更新ringbuffer的使用量
r.use = (start+size-r.start)%size
return true
}
return false
}
func (r *Ringbuffer) Read(b []byte) int{
if r.use > 0 {//判断是非还有未读数据
//获取block的长度
size_byte:=make([]byte,4)
t:=copy(size_byte,r.buf[r.start:])
if t!=4 {//判断有没有被分割开
copy(size_byte[t:4],r.buf[:])
}
rblock_size:= ByteToInt(size_byte)
//获取block的内容
start:=(r.start+4)%len(r.buf)
nread:=0
if start+rblock_size >= len(r.buf) {
n:= copy(b,r.buf[start:])//判断数据包内容有没有被分割
nread = copy(b[n:],r.buf[:])
nread = nread + n
}else{
nread = copy(b,r.buf[start:start+rblock_size])
}
if nread == rblock_size {
r.start = (r.start + rblock_size + 4)%len(r.buf)
r.use = r.use - rblock_size - 4
return nread
}else{
return -1
}
}
return 0
}
func (r *Ringbuffer) GetUse() int{
return r.use
}