kcp_test.go 7.0 KB

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