码农在处理通讯业务的时候,经常会涉及到数据包的顺序问题。尤其IP网的多态性,UDP数据包在发送到接收的过程中,无法做到先发先收(TCP协议内部实现了滑动窗口下的重新排序),在很多情况下都需要自己来重新排序规整数据。
// ShiftWin 滑动窗口,UDP导致的数据包顺序被打乱恢复
type Node struct{
serial int // 节点序号
cTime int64 // 时间戳
data []byte // 数据内容
next *Node
prev *Node
}
type ShiftWin struct {
head *Node // 插入时确保从小到大,翻转出口
tail *Node // 数据有时间,正常是有序,所以从后往前找,可以减少消耗
outChan chan []byte // 超时及溢出数据出口
count int
size int
timeout int64
}
// 超时检测
func timeoutdetect(self *ShiftWin){
// 超时检测
for self.timeout>0 {
if(self.count>0){
if(time.Now().Unix()-self.head.cTime > self.timeout){
self.outChan <-self.head.data
self.head=self.head.next
if self.head != nil{
self.head.prev=nil
self.count–
}else{
self.count=0
}
}
}
time.Sleep(time.Second)
}
}
func newShifWin(rch chan []byte, size int,timeout int64) *ShiftWin{
sw:=ShiftWin{
size: size,
timeout: timeout,
outChan: rch,
}
// 创建超时检测协程?每个元素/一个滑动窗口一个协程
go timeoutdetect(&sw)
return &sw
}
func serialBefore(seq1 int,seq2 int) bool{
interval:=seq2-seq1
if (interval>0 && interval<32768)||(interval < (-32768)){
return true
}
return false
}
func cleanShiftWin(self *ShiftWin){
for self.head!=nil {
fmt.Println(“Node:”,string(self.head.data))
self.head=self.head.next
}
}
func InsertShiftWin(self *ShiftWin,serial int,data []byte){
//fmt.Println(“Append:”,serial,”Count:”,self.count)
node:=Node{
serial:serial,
data:data,
cTime:time.Now().Unix(),
}
if self.count==0{
self.count=1
self.head=&node
self.tail=&node
return
}
if(self.count<self.size){
self.count++
}else{
// 达到容量,弹出最前面的数据
self.outChan<-self.head.data
self.head=self.head.next
self.head.prev=nil
}
if serialBefore(self.tail.serial,serial){
//fmt.Println(“Append tail”)
node.prev=self.tail
self.tail.next=&node
self.tail=&node
}else{
cur:=self.tail.prev
for (cur!=nil)&&serialBefore(serial,cur.serial){
// 找到插入点
cur=cur.prev
}
if cur!=nil{
//fmt.Println(“Append data”,serial)
cur.next.prev=&node
node.next=cur.next
cur.next=&node
node.prev=cur
}else{ // 头部插入
//fmt.Println(“Append Head”)
node.next=self.head
self.head.prev=&node
self.head=&node
}
}
}
代码堆出来,有兴趣的可以自己去玩玩。其实发现无论用哪种编程语言,编程方法都是一样的,思想决定代码。顺带谴责一下用代码量来考核编程工作量的行径。诚然我也不知道该如何去衡量一个程序员的工作量。
写程序有时候就是在做创作,好的思路和实现,会带来发自内心的愉悦。