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  }