github.com/shaoyuan1943/gokcp@v0.0.0-20201026071748-5b36d4c87f61/kcp_test.go (about) 1 package gokcp 2 3 import ( 4 "container/list" 5 "encoding/binary" 6 "math/rand" 7 "testing" 8 "time" 9 ) 10 11 type DelayPacket struct { 12 data []byte 13 Ts uint32 14 } 15 16 func NewDelayPacket(data []byte) *DelayPacket { 17 dp := &DelayPacket{ 18 data: nil, 19 Ts: 0, 20 } 21 22 dp.data = make([]byte, len(data)) 23 copy(dp.data, data) 24 return dp 25 } 26 27 type Random struct { 28 seeds []int 29 size int 30 } 31 32 func (r *Random) Rand() int { 33 if len(r.seeds) == 0 { 34 return 0 35 } 36 37 if r.size == 0 { 38 for i := 0; i < len(r.seeds); i++ { 39 r.seeds[i] = i 40 } 41 42 r.size = len(r.seeds) 43 } 44 45 v := rand.Int() % r.size 46 x := r.seeds[v] 47 r.size -= 1 48 r.seeds[v] = r.seeds[r.size] 49 return x 50 } 51 52 func NewRandom(size int) *Random { 53 r := &Random{} 54 r.seeds = make([]int, size) 55 return r 56 } 57 58 func TestRandom(t *testing.T) { 59 rand.Seed(time.Now().UnixNano()) 60 randomValues := make([]int, 1000) 61 random := NewRandom(100) 62 for i := 0; i < 1000; i++ { 63 randomValues[i] = random.Rand() 64 } 65 66 t.Logf("randomValues: %v", randomValues) 67 } 68 69 type LatencySimulator struct { 70 lostRate int // 丢包率 71 rttMin int // 最小往返时间 72 rttMax int // 最大往返时间 73 max int 74 rand12 *Random 75 dt12 *list.List 76 rand21 *Random 77 dt21 *list.List 78 TX1 int 79 TX2 int 80 } 81 82 func NewLatencySimulator(lostRate, rttMin, rttMax, max int) *LatencySimulator { 83 ls := &LatencySimulator{ 84 lostRate: lostRate / 2, 85 rttMin: rttMin / 2, 86 rttMax: rttMax / 2, 87 max: max, 88 } 89 90 ls.rand12 = NewRandom(100) 91 ls.dt12 = list.New() 92 93 ls.rand21 = NewRandom(100) 94 ls.dt21 = list.New() 95 return ls 96 } 97 98 // 发送数据 99 // peer - 端点0/1,从0发送,从1接收;从1发送从0接收 100 func (ls *LatencySimulator) Send(peer int, data []byte) { 101 if peer == 0 { 102 ls.TX1++ 103 if ls.rand12.Rand() < ls.lostRate { 104 return 105 } 106 107 if ls.dt12.Len() >= ls.max { 108 return 109 } 110 } else { 111 ls.TX2++ 112 if ls.rand21.Rand() < ls.lostRate { 113 return 114 } 115 116 if ls.dt21.Len() >= ls.max { 117 return 118 } 119 } 120 121 packet := NewDelayPacket(data) 122 current := CurrentMS() 123 delay := ls.rttMin 124 if ls.rttMax > ls.rttMin { 125 delay += rand.Int() % (ls.rttMax - ls.rttMin) 126 } 127 packet.Ts = current + uint32(delay) 128 if peer == 0 { 129 ls.dt12.PushBack(packet) 130 } else { 131 ls.dt21.PushBack(packet) 132 } 133 } 134 135 func (ls *LatencySimulator) Recv(peer int, data []byte, max int) int { 136 var ele *list.Element 137 if peer == 0 { 138 if ls.dt21.Len() == 0 { 139 return -1 140 } else { 141 ele = ls.dt21.Front() 142 } 143 } else { 144 if ls.dt12.Len() == 0 { 145 return -1 146 } else { 147 ele = ls.dt12.Front() 148 } 149 } 150 151 packet := ele.Value.(*DelayPacket) 152 current := CurrentMS() 153 if current < packet.Ts { 154 return -2 155 } 156 157 if max < len(packet.data) { 158 return -3 159 } 160 161 if peer == 0 { 162 ls.dt21.Remove(ele) 163 } else { 164 ls.dt12.Remove(ele) 165 } 166 167 max = len(packet.data) 168 data = data[:max] 169 copy(data, packet.data) 170 return max 171 } 172 173 var vnet *LatencySimulator 174 175 func testKCP(t *testing.T, mode int, modestr string) { 176 vnet = NewLatencySimulator(10, 60, 125, 1000) 177 kcp1 := NewKCP(0x11223344, func(p []byte) { 178 vnet.Send(0, p) 179 t.Logf("kcp1 output: %v", p) 180 }) 181 182 kcp2 := NewKCP(0x11223344, func(p []byte) { 183 vnet.Send(1, p) 184 t.Logf("kcp2 output: %v", p) 185 }) 186 187 current := CurrentMS() 188 var slap uint32 = current + uint32(20) 189 var index uint32 190 var next uint32 191 var summaryRTT uint32 192 193 count := 0 194 maxRTT := 0 195 196 kcp1.SetWndSize(128, 128) 197 kcp2.SetWndSize(128, 128) 198 199 if mode == 0 { 200 kcp1.SetNoDelay(false, 10, 0, false) 201 kcp2.SetNoDelay(false, 10, 0, false) 202 } else if mode == 1 { 203 kcp1.SetNoDelay(false, 10, 0, true) 204 kcp2.SetNoDelay(false, 10, 0, true) 205 } else { 206 kcp1.SetNoDelay(true, 10, 2, true) 207 kcp2.SetNoDelay(true, 10, 2, true) 208 209 kcp1.rxMinRTO = 10 210 kcp1.fastResendACK = 1 211 } 212 213 kcp1Sended := 0 214 loops := 0 215 buffer := make([]byte, 2000) 216 ts1 := CurrentMS() 217 for { 218 loops++ 219 <-time.After(1 * time.Millisecond) 220 221 current = CurrentMS() 222 kcp1.Update() 223 kcp2.Update() 224 225 // 每隔 20ms,kcp1发送数据 226 for ; current >= slap; slap += 20 { 227 binary.LittleEndian.PutUint32(buffer[0:4], uint32(index)) 228 binary.LittleEndian.PutUint32(buffer[4:8], uint32(current)) 229 kcp1.Send(buffer[0:8]) 230 index++ 231 kcp1Sended++ 232 break 233 } 234 t.Logf("kcp1Sended: %v", kcp1Sended) 235 236 // 处理虚拟网络:检测是否有udp包从p1->p2 237 for { 238 hr := vnet.Recv(1, buffer, 2000) 239 if hr < 0 { 240 break 241 } 242 243 t.Logf("kcp2 recved,len: %v", hr) 244 // 如果 p2收到udp,则作为下层协议输入到kcp2 245 kcp2.Input(buffer[:hr]) 246 } 247 248 // 处理虚拟网络:检测是否有udp包从p2->p1 249 for { 250 hr := vnet.Recv(0, buffer, 2000) 251 if hr < 0 { 252 break 253 } 254 255 t.Logf("kcp1 recved, len: %v", hr) 256 // 如果 p1收到udp,则作为下层协议输入到kcp1 257 kcp1.Input(buffer[:hr]) 258 } 259 260 // kcp2接收到任何包都返回回去 261 for { 262 hr, err := kcp2.Recv(buffer) 263 if err != nil { 264 break 265 } 266 267 t.Logf("kcp2.Send: %v", hr) 268 // 如果收到包就回射 269 kcp2.Send(buffer[:hr]) 270 } 271 272 // kcp1收到kcp2的回射数据 273 for { 274 hr, err := kcp1.Recv(buffer) 275 if err != nil { 276 break 277 } 278 t.Logf("kcp1 recved: %v", hr) 279 280 sn := binary.LittleEndian.Uint32(buffer[0:4]) 281 ts := binary.LittleEndian.Uint32(buffer[4:8]) 282 rtt := current - ts 283 if sn != next { 284 // 如果收到的包不连续 285 t.Logf("ERROR sn %v <-> %v", count, next) 286 return 287 } 288 289 next++ 290 summaryRTT += rtt 291 count++ 292 if rtt > uint32(maxRTT) { 293 maxRTT = int(rtt) 294 } 295 t.Logf("[RECV] mode=%v, sn=%v, rtt=%v", mode, sn, rtt) 296 } 297 298 if next > 1 || loops > 5 { 299 break 300 } 301 } 302 303 ts1 = CurrentMS() - ts1 304 t.Logf("%s mode result: %vms", modestr, ts1) 305 t.Logf("avgrtt=%v maxrtt=%v tx=%v", int(summaryRTT)/count, maxRTT, vnet.TX1) 306 } 307 308 func TestKCP(t *testing.T) { 309 rand.Seed(time.Now().UnixNano()) 310 testKCP(t, 0, "default") 311 //testKCP(t, 1, "normal") 312 //testKCP(t, 2, "fast") 313 }