介绍
testkcp.lua为lua-kcp项目的测试脚本入口文件,它主要通过模拟网络和 KCP 实例的收发数据,对比默认/普通/快速三种模式来进行 KCP 的测试,并显示相关的统计信息
代码分析
- 设置 Lua 的模块搜索路径(package.path)、C 库搜索路径(package.cpath)和导入所需的模块。
package.cpath = package.cpath .. ";./lualib/?.so"
package.path = package.path .. ";./src/?.lua"
local LatencySM = require "latencysm"
local LKcp = require "lkcp"
local LUtil = require "lutil"
- 创建模拟网络对象 LatencySM,并设置丢包率为 10%,RTT(Round-Trip Time,往返时间)为 60-125 毫秒。
local lsm = LatencySM.LatencySM.new(10, 60, 125)
- 定义 getms 函数,用于获取当前时间戳的毫秒数。
local function getms()
return math.floor(LUtil.gettimeofday())
end
- 定义 udp_output 函数,作为 KCP 的相应输出接口调用。在这个函数中,打印一些信息,并通过模拟网络对象发送数据包。
local function udp_output(buf, info)
print(info.id, info.a, info.b, info.c)
if info.b then
info.c(info.a)
end
lsm:send(info.id, buf)
end
- 定义 test 函数,用于进行 KCP 测试。该函数接受一个 mode 参数,用于确定 KCP 的运行模式。
local function test(mode)
-- ... 函数中的具体实现略过 ...
end
- 在 test 函数内部,创建两个 KCP 实例对象 kcp1 和 kcp2,以及相应的输出信息。
这里还设置了窗口大小为 128,根据测试用例的 mode,配置不同的 KCP 行为。
-- 创建 kcp1 和 kcp2 对象
local kcp1 = LKcp.lkcp_create(session, function (buf)
udp_output(buf, info)
end)
local kcp2 = LKcp.lkcp_create(session, function (buf)
udp_output(buf, info2)
end)
-- 设置窗口大小
kcp1:lkcp_wndsize(128, 128)
kcp2:lkcp_wndsize(128, 128)
-- 根据 mode 进行不同的 KCP 配置
if mode == 0 then
-- 默认模式
kcp1:lkcp_nodelay(0, 10, 0, 0)
kcp2:lkcp_nodelay(0, 10, 0, 0)
elseif mode == 1 then
-- 普通模式,关闭流控等
kcp1:lkcp_nodelay(0, 10, 0, 1)
kcp2:lkcp_nodelay(0, 10, 0, 1)
else
-- 启动快速模式
-- ... 具体参数的含义略过 ...
kcp1:lkcp_nodelay(1, 10, 2, 1)
kcp2:lkcp_nodelay(1, 10, 2, 1)
end
- 在 KCP 测试之前的准备工作已完成,接下来进入主循环处理数据的收发和更新。
while 1 do
-- ... 主循环中的具体实现略过 ...
end
- 在主循环中,首先获取当前时间戳并进行处理,包括 KCP 更新和收发数据等。
current = getms()
local nextt1 = kcp1:lkcp_check(current)
local nextt2 = kcp2:lkcp_check(current)
local nextt = math.min(nextt1, nextt2)
local diff = nextt - current
if diff > 0 then
LUtil.isleep(diff)
current = getms()
end
kcp1:lkcp_update(current)
kcp2:lkcp_update(current)
- 在主循环中,每隔 20 毫秒(根据 slap 时间),kcp1 发送数据。
while current >= slap do
local s1 = LUtil.uint322netbytes(index)
local s2 = LUtil.uint322netbytes(current)
kcp1:lkcp_send(s1..s2)
slap = slap + 20
index = index + 1
end
- 在主循环中,处理虚拟网络,检测是否有 UDP 包从 p1(kcp1)发往 p2(kcp2),并作为下层协议输入到 kcp2。
while 1 do
hrlen, hr = lsm:recv(1)
if hrlen < 0 then
break
end
kcp2:lkcp_input(hr)
end
- 在主循环中,处理虚拟网络,检测是否有 UDP 包从 p2(kcp2)发往 p1(kcp1),并作为下层协议输入到 kcp1。
while 1 do
hrlen, hr = lsm:recv(0)
if hrlen < 0 then
break
end
kcp1:lkcp_input(hr)
end
- 在主循环中,处理 kcp2 收到的数据包,先接收并回射数据。
while 1 do
hrlen, hr = kcp2:lkcp_recv()
if hrlen <= 0 then
break
end
kcp2:lkcp_send(hr)
end
- 在主循环中,处理 kcp1 收到的数据包,计算并显示相关统计信息。
while 1 do
hrlen, hr = kcp1:lkcp_recv()
if hrlen <= 0 then
break
end
-- 统计相关信息
local hr1 = string.sub(hr, 1, 4)
local hr2 = string.sub(hr, 5, 8)
local sn = LUtil.netbytes2uint32(hr1)
local ts = LUtil.netbytes2uint32(hr2)
local rtt = current - ts
if sn ~= inext then
-- 如果收到的包不连续
print(string.format("ERROR sn %d<->%d\n", count, inext))
return
end
inext = inext + 1
sumrtt = sumrtt + rtt
count = count + 1
if rtt > maxrtt then
maxrtt = rtt
end
print(string.format("[RECV] mode=%d sn=%d rtt=%d, ts=%d inext=%d\n", mode, sn, rtt, ts, inext))
end
- 在 test 函数内部,打印测试结果,包括运行模式(mode),总消耗时间(ts1),平均 RTT(avgrtt)和最大 RTT(maxrtt)。
ts1 = getms() - ts1
names = {"default", "normal", "fast"}
print(string.format("%s mode result (%dms):", names[mode+1], ts1))
print(string.format("avgrtt=%d maxrtt=%d", math.floor(sumrtt/count), maxrtt))
print("press enter to next ...")
io.read()
- 最后,进行三种模式的 KCP 测试。
test(0) -- 默认模式,类似 TCP:正常模式,无快速重传,常规流控
test(1) -- 普通模式,关闭流控等
test(2) -- 快速模式,所有开关都打开,且关闭流控
运行数据示例
[root@localhost lua-kcp]# ./run_test.sh
0 aaa false nil
1 aaaaaaaaaaaaa true function: 0x1708910
hahahah!!!
[RECV] mode=0 sn=0 rtt=91, ts=1801875059 inext=1
0 aaa false nil
1 aaaaaaaaaaaaa true function: 0x1708910
hahahah!!!
[RECV] mode=0 sn=1 rtt=151, ts=1801875079 inext=2
[RECV] mode=0 sn=2 rtt=131, ts=1801875099 inext=3
0 aaa false nil
1 aaaaaaaaaaaaa true function: 0x1708910
hahahah!!!
[RECV] mode=0 sn=3 rtt=200, ts=1801875120 inext=4
[RECV] mode=0 sn=4 rtt=180, ts=1801875140 inext=5
[RECV] mode=0 sn=5 rtt=161, ts=1801875159 inext=6
0 aaa false nil
1 aaaaaaaaaaaaa true function: 0x1708910
hahahah!!!
[RECV] mode=0 sn=6 rtt=230, ts=1801875180 inext=7
[RECV] mode=0 sn=7 rtt=210, ts=1801875200 inext=8
[RECV] mode=0 sn=8 rtt=190, ts=1801875220 inext=9
[RECV] mode=0 sn=9 rtt=171, ts=1801875239 inext=10
0 aaa false nil
1 aaaaaaaaaaaaa true function: 0x1708910
hahahah!!!
[RECV] mode=0 sn=10 rtt=230, ts=1801875260 inext=11
[RECV] mode=0 sn=11 rtt=210, ts=1801875280 inext=12
[RECV] mode=0 sn=12 rtt=191, ts=1801875299 inext=13
[RECV] mode=0 sn=13 rtt=170, ts=1801875320 inext=14
[RECV] mode=0 sn=14 rtt=151, ts=1801875339 inext=15
default mode result (451ms):
avgrtt=177 maxrtt=230
press enter to next ...
0 aaa false nil
0 aaa false nil
0 aaa false nil
1 aaaaaaaaaaaaa true function: 0x1708910
hahahah!!!
0 aaa false nil
1 aaaaaaaaaaaaa true function: 0x1708910
hahahah!!!
0 aaa false nil
[RECV] mode=1 sn=0 rtt=91, ts=1801884496 inext=1
0 aaa false nil
1 aaaaaaaaaaaaa true function: 0x1708910
hahahah!!!
[RECV] mode=1 sn=1 rtt=79, ts=1801884517 inext=2
0 aaa false nil
1 aaaaaaaaaaaaa true function: 0x1708910
hahahah!!!
0 aaa false nil
1 aaaaaaaaaaaaa true function: 0x1708910
hahahah!!!
[RECV] mode=1 sn=2 rtt=91, ts=1801884536 inext=3
0 aaa false nil
[RECV] mode=1 sn=3 rtt=80, ts=1801884557 inext=4
0 aaa false nil
1 aaaaaaaaaaaaa true function: 0x1708910
hahahah!!!
0 aaa false nil
[RECV] mode=1 sn=4 rtt=91, ts=1801884576 inext=5
0 aaa false nil
1 aaaaaaaaaaaaa true function: 0x1708910
hahahah!!!
[RECV] mode=1 sn=5 rtt=81, ts=1801884596 inext=6
0 aaa false nil
1 aaaaaaaaaaaaa true function: 0x1708910
hahahah!!!
0 aaa false nil
1 aaaaaaaaaaaaa true function: 0x1708910
hahahah!!!
0 aaa false nil
1 aaaaaaaaaaaaa true function: 0x1708910
hahahah!!!
0 aaa false nil
0 aaa false nil
1 aaaaaaaaaaaaa true function: 0x1708910
hahahah!!!
0 aaa false nil
1 aaaaaaaaaaaaa true function: 0x1708910
hahahah!!!
0 aaa false nil
0 aaa false nil
0 aaa false nil
1 aaaaaaaaaaaaa true function: 0x1708910
hahahah!!!
0 aaa false nil
1 aaaaaaaaaaaaa true function: 0x1708910
hahahah!!!
0 aaa false nil
1 aaaaaaaaaaaaa true function: 0x1708910
hahahah!!!
0 aaa false nil
1 aaaaaaaaaaaaa true function: 0x1708910
hahahah!!!
[RECV] mode=1 sn=6 rtt=258, ts=1801884619 inext=7
[RECV] mode=1 sn=7 rtt=240, ts=1801884637 inext=8
[RECV] mode=1 sn=8 rtt=221, ts=1801884656 inext=9
[RECV] mode=1 sn=9 rtt=200, ts=1801884677 inext=10
[RECV] mode=1 sn=10 rtt=181, ts=1801884696 inext=11
[RECV] mode=1 sn=11 rtt=161, ts=1801884716 inext=12
normal mode result (401ms):
avgrtt=147 maxrtt=258
press enter to next ...
1 aaaaaaaaaaaaa true function: 0x1708910
hahahah!!!
0 aaa false nil
0 aaa false nil
0 aaa false nil
1 aaaaaaaaaaaaa true function: 0x1708910
hahahah!!!
0 aaa false nil
1 aaaaaaaaaaaaa true function: 0x1708910
hahahah!!!
[RECV] mode=2 sn=0 rtt=79, ts=1801886545 inext=1
0 aaa false nil
1 aaaaaaaaaaaaa true function: 0x1708910
hahahah!!!
0 aaa false nil
[RECV] mode=2 sn=1 rtt=91, ts=1801886564 inext=2
0 aaa false nil
1 aaaaaaaaaaaaa true function: 0x1708910
hahahah!!!
0 aaa false nil
[RECV] mode=2 sn=2 rtt=90, ts=1801886585 inext=3
0 aaa false nil
1 aaaaaaaaaaaaa true function: 0x1708910
hahahah!!!
0 aaa false nil
1 aaaaaaaaaaaaa true function: 0x1708910
hahahah!!!
[RECV] mode=2 sn=3 rtt=91, ts=1801886604 inext=4
0 aaa false nil
0 aaa false nil
1 aaaaaaaaaaaaa true function: 0x1708910
hahahah!!!
[RECV] mode=2 sn=4 rtt=101, ts=1801886624 inext=5
[RECV] mode=2 sn=5 rtt=81, ts=1801886644 inext=6
0 aaa false nil
1 aaaaaaaaaaaaa true function: 0x1708910
hahahah!!!
0 aaa false nil
1 aaaaaaaaaaaaa true function: 0x1708910
hahahah!!!
[RECV] mode=2 sn=6 rtt=91, ts=1801886664 inext=7
0 aaa false nil
[RECV] mode=2 sn=7 rtt=79, ts=1801886685 inext=8
0 aaa false nil
1 aaaaaaaaaaaaa true function: 0x1708910
hahahah!!!
[RECV] mode=2 sn=8 rtt=81, ts=1801886704 inext=9
0 aaa false nil
1 aaaaaaaaaaaaa true function: 0x1708910
hahahah!!!
[RECV] mode=2 sn=9 rtt=79, ts=1801886725 inext=10
0 aaa false nil
1 aaaaaaaaaaaaa true function: 0x1708910
hahahah!!!
[RECV] mode=2 sn=10 rtt=80, ts=1801886745 inext=11
fast mode result (302ms):
avgrtt=85 maxrtt=101
press enter to next ...