kcp_test.go 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  1. package kcp
  2. import (
  3. "bytes"
  4. "container/list"
  5. "encoding/binary"
  6. "fmt"
  7. "math/rand"
  8. "sync"
  9. "testing"
  10. "time"
  11. )
  12. func iclock() int32 {
  13. return int32((time.Now().UnixNano() / 1000000) & 0xffffffff)
  14. }
  15. type DelayPacket struct {
  16. _ptr []byte
  17. _size int
  18. _ts int32
  19. }
  20. func (p *DelayPacket) Init(size int, src []byte) {
  21. p._ptr = make([]byte, size)
  22. p._size = size
  23. copy(p._ptr, src[:size])
  24. }
  25. func (p *DelayPacket) ptr() []byte { return p._ptr }
  26. func (p *DelayPacket) size() int { return p._size }
  27. func (p *DelayPacket) ts() int32 { return p._ts }
  28. func (p *DelayPacket) setts(ts int32) { p._ts = ts }
  29. type DelayTunnel struct{ *list.List }
  30. type Random *rand.Rand
  31. type LatencySimulator struct {
  32. current int32
  33. lostrate, rttmin, rttmax, nmax int
  34. p12 DelayTunnel
  35. p21 DelayTunnel
  36. r12 *rand.Rand
  37. r21 *rand.Rand
  38. }
  39. // lostrate: 往返一周丢包率的百分比,默认 10%
  40. // rttmin:rtt最小值,默认 60
  41. // rttmax:rtt最大值,默认 125
  42. //func (p *LatencySimulator)Init(int lostrate = 10, int rttmin = 60, int rttmax = 125, int nmax = 1000):
  43. func (p *LatencySimulator) Init(lostrate, rttmin, rttmax, nmax int) {
  44. p.r12 = rand.New(rand.NewSource(9))
  45. p.r21 = rand.New(rand.NewSource(99))
  46. p.p12 = DelayTunnel{list.New()}
  47. p.p21 = DelayTunnel{list.New()}
  48. p.current = iclock()
  49. p.lostrate = lostrate / 2 // 上面数据是往返丢包率,单程除以2
  50. p.rttmin = rttmin / 2
  51. p.rttmax = rttmax / 2
  52. p.nmax = nmax
  53. }
  54. // 发送数据
  55. // peer - 端点0/1,从0发送,从1接收;从1发送从0接收
  56. func (p *LatencySimulator) send(peer int, data []byte, size int) int {
  57. rnd := 0
  58. if peer == 0 {
  59. rnd = p.r12.Intn(100)
  60. } else {
  61. rnd = p.r21.Intn(100)
  62. }
  63. //println("!!!!!!!!!!!!!!!!!!!!", rnd, p.lostrate, peer)
  64. if rnd < p.lostrate {
  65. return 0
  66. }
  67. pkt := &DelayPacket{}
  68. pkt.Init(size, data)
  69. p.current = iclock()
  70. delay := p.rttmin
  71. if p.rttmax > p.rttmin {
  72. delay += rand.Int() % (p.rttmax - p.rttmin)
  73. }
  74. pkt.setts(p.current + int32(delay))
  75. if peer == 0 {
  76. p.p12.PushBack(pkt)
  77. } else {
  78. p.p21.PushBack(pkt)
  79. }
  80. return 1
  81. }
  82. // 接收数据
  83. func (p *LatencySimulator) recv(peer int, data []byte, maxsize int) int32 {
  84. var it *list.Element
  85. if peer == 0 {
  86. it = p.p21.Front()
  87. if p.p21.Len() == 0 {
  88. return -1
  89. }
  90. } else {
  91. it = p.p12.Front()
  92. if p.p12.Len() == 0 {
  93. return -1
  94. }
  95. }
  96. pkt := it.Value.(*DelayPacket)
  97. p.current = iclock()
  98. if p.current < pkt.ts() {
  99. return -2
  100. }
  101. if maxsize < pkt.size() {
  102. return -3
  103. }
  104. if peer == 0 {
  105. p.p21.Remove(it)
  106. } else {
  107. p.p12.Remove(it)
  108. }
  109. maxsize = pkt.size()
  110. copy(data, pkt.ptr()[:maxsize])
  111. return int32(maxsize)
  112. }
  113. //=====================================================================
  114. //=====================================================================
  115. // 模拟网络
  116. var vnet *LatencySimulator
  117. // 测试用例
  118. func test(mode int) {
  119. // 创建模拟网络:丢包率10%,Rtt 60ms~125ms
  120. vnet = &LatencySimulator{}
  121. vnet.Init(10, 60, 125, 1000)
  122. // 创建两个端点的 kcp对象,第一个参数 conv是会话编号,同一个会话需要相同
  123. // 最后一个是 user参数,用来传递标识
  124. output1 := func(buf []byte, size int) {
  125. if vnet.send(0, buf, size) != 1 {
  126. }
  127. }
  128. output2 := func(buf []byte, size int) {
  129. if vnet.send(1, buf, size) != 1 {
  130. }
  131. }
  132. kcp1 := NewKCP(0x11223344, output1)
  133. kcp2 := NewKCP(0x11223344, output2)
  134. current := uint32(iclock())
  135. slap := current + 20
  136. index := 0
  137. next := 0
  138. var sumrtt uint32
  139. count := 0
  140. maxrtt := 0
  141. // 配置窗口大小:平均延迟200ms,每20ms发送一个包,
  142. // 而考虑到丢包重发,设置最大收发窗口为128
  143. kcp1.WndSize(128, 128)
  144. kcp2.WndSize(128, 128)
  145. // 判断测试用例的模式
  146. if mode == 0 {
  147. // 默认模式
  148. kcp1.NoDelay(0, 10, 0, 0)
  149. kcp2.NoDelay(0, 10, 0, 0)
  150. } else if mode == 1 {
  151. // 普通模式,关闭流控等
  152. kcp1.NoDelay(0, 10, 0, 1)
  153. kcp2.NoDelay(0, 10, 0, 1)
  154. } else {
  155. // 启动快速模式
  156. // 第二个参数 nodelay-启用以后若干常规加速将启动
  157. // 第三个参数 interval为内部处理时钟,默认设置为 10ms
  158. // 第四个参数 resend为快速重传指标,设置为2
  159. // 第五个参数 为是否禁用常规流控,这里禁止
  160. kcp1.NoDelay(1, 10, 2, 1)
  161. kcp2.NoDelay(1, 10, 2, 1)
  162. }
  163. buffer := make([]byte, 2000)
  164. var hr int32
  165. ts1 := iclock()
  166. for {
  167. time.Sleep(1 * time.Millisecond)
  168. current = uint32(iclock())
  169. kcp1.Update()
  170. kcp2.Update()
  171. // 每隔 20ms,kcp1发送数据
  172. for ; current >= slap; slap += 20 {
  173. buf := new(bytes.Buffer)
  174. binary.Write(buf, binary.LittleEndian, uint32(index))
  175. index++
  176. binary.Write(buf, binary.LittleEndian, uint32(current))
  177. // 发送上层协议包
  178. kcp1.Send(buf.Bytes())
  179. //println("now", iclock())
  180. }
  181. // 处理虚拟网络:检测是否有udp包从p1->p2
  182. for {
  183. hr = vnet.recv(1, buffer, 2000)
  184. if hr < 0 {
  185. break
  186. }
  187. // 如果 p2收到udp,则作为下层协议输入到kcp2
  188. kcp2.Input(buffer[:hr], true, false)
  189. }
  190. // 处理虚拟网络:检测是否有udp包从p2->p1
  191. for {
  192. hr = vnet.recv(0, buffer, 2000)
  193. if hr < 0 {
  194. break
  195. }
  196. // 如果 p1收到udp,则作为下层协议输入到kcp1
  197. kcp1.Input(buffer[:hr], true, false)
  198. //println("@@@@", hr, r)
  199. }
  200. // kcp2接收到任何包都返回回去
  201. for {
  202. hr = int32(kcp2.Recv(buffer[:10]))
  203. // 没有收到包就退出
  204. if hr < 0 {
  205. break
  206. }
  207. // 如果收到包就回射
  208. buf := bytes.NewReader(buffer)
  209. var sn uint32
  210. binary.Read(buf, binary.LittleEndian, &sn)
  211. kcp2.Send(buffer[:hr])
  212. }
  213. // kcp1收到kcp2的回射数据
  214. for {
  215. hr = int32(kcp1.Recv(buffer[:10]))
  216. buf := bytes.NewReader(buffer)
  217. // 没有收到包就退出
  218. if hr < 0 {
  219. break
  220. }
  221. var sn uint32
  222. var ts, rtt uint32
  223. binary.Read(buf, binary.LittleEndian, &sn)
  224. binary.Read(buf, binary.LittleEndian, &ts)
  225. rtt = uint32(current) - ts
  226. if sn != uint32(next) {
  227. // 如果收到的包不连续
  228. //for i:=0;i<8 ;i++ {
  229. //println("---", i, buffer[i])
  230. //}
  231. println("ERROR sn ", count, "<->", next, sn)
  232. return
  233. }
  234. next++
  235. sumrtt += rtt
  236. count++
  237. if rtt > uint32(maxrtt) {
  238. maxrtt = int(rtt)
  239. }
  240. //println("[RECV] mode=", mode, " sn=", sn, " rtt=", rtt)
  241. }
  242. if next > 100 {
  243. break
  244. }
  245. }
  246. ts1 = iclock() - ts1
  247. names := []string{"default", "normal", "fast"}
  248. fmt.Printf("%s mode result (%dms):\n", names[mode], ts1)
  249. fmt.Printf("avgrtt=%d maxrtt=%d\n", int(sumrtt/uint32(count)), maxrtt)
  250. }
  251. func TestNetwork(t *testing.T) {
  252. test(0) // 默认模式,类似 TCP:正常模式,无快速重传,常规流控
  253. test(1) // 普通模式,关闭流控等
  254. test(2) // 快速模式,所有开关都打开,且关闭流控
  255. }
  256. func BenchmarkFlush(b *testing.B) {
  257. kcp := NewKCP(1, func(buf []byte, size int) {})
  258. kcp.snd_buf = make([]segment, 32)
  259. for k := range kcp.snd_buf {
  260. kcp.snd_buf[k].xmit = 1
  261. kcp.snd_buf[k].resendts = currentMs() + 10000
  262. }
  263. b.ResetTimer()
  264. b.ReportAllocs()
  265. var mu sync.Mutex
  266. for i := 0; i < b.N; i++ {
  267. mu.Lock()
  268. kcp.flush(false)
  269. mu.Unlock()
  270. }
  271. }