弱网重连时服务器补发的背包消息和本地已处理的重复,道具出现双份显示,重连一次就多一批幻影道具。消息去重在处理回调前加一道序号过滤,重复包直接丢弃,幻影从此消失。过滤器放在客户端入口而不是服务器端,是为了把重复包挡在界面刷新之前,省掉一轮无效渲染。过滤器本身是几十行的纯本地逻辑,无额外网络开销,任何消息型界面都能复用。
每条业务消息带递增序号,按通道记录已处理的最大序号,小于等于记录值的一律判重,乱序与重复都能拦住。
local lastSeq = {}
local chTime = {}
local function isDup(ch, seq)
local last = lastSeq[ch] or 0
if seq <= last then return true end
lastSeq[ch] = seq
chTime[ch] = os.time()
return false
end
回调里先过过滤器,重复包静默丢弃并计数,单轮丢弃超过 50 条提示网络波动;通道 3600 秒无消息自动清表,防止表无限增长。
local dropCnt = 0
SL:RegisterLuaNetMsg(7001, function(data)
if isDup(1, data.seq) then
dropCnt = dropCnt + 1
if dropCnt > 50 then
SL:ShowSystemTips("网络波动,已忽略 " .. dropCnt .. " 条重复数据")
dropCnt = 0
end
return
end
refreshBag(data)
end)
SL:Schedule(function()
local now = os.time()
for ch, ts in pairs(chTime) do
if now - ts > 3600 then
lastSeq[ch] = nil
chTime[ch] = nil
end
end
end, 600)
造重复序号与乱序序号各 200 条灌入,核对界面道具数与服务器账目一致;真机弱网重连 20 次,幻影道具零出现;客户端过滤计数与服务器补发日志对账一致。监控每千人重连的过滤包数,突增说明服务器补发窗口过大。通道复位逻辑单独验证:静置一小时后旧序号重放应被放行,确认清表生效。
序号从 1 开始且重连后服务器重新计数,客户端沿用旧表会把新会话全部判重,重连成功事件里必须清空 lastSeq,这条没做之前玩家重连后背包全空。序号比较一度用浮点,超长会话出现精度误差导致误判,改回整数比较。提示文案初版带了第二人称,被文案规范打回,游戏内提示统一第三人称。乱序包直接丢弃会漏数据,当前方案以序号只增协议为前提,协议调整时要同步改过滤器。dropCnt 的清零点放在提示之后,连续弱网下每满 50 条报一次,不会刷屏。
全站技术干货持续更新:996 引擎 / Lua 实战帖,语法、参数与示例一篇讲透。进入文章地图 · 查看全部 →
实战应用:用在哪里 装备回收商 NPC 每天按评分收购玩家的装备,裁决之杖、骨玉权杖按攻击、持久加权打分,榜上只要前五名。数…
实战应用:用在哪里 沙巴克攻城是全服行会战的最高舞台:攻方砸开城门、抢占皇宫,守方依托城墙与复活点反打。规则设计的关键是节奏…
实战应用:用在哪里 影分身玩法给法师职业补上生存短板:危急时刻召唤四个影分身分担仇恨,敌人需要在六格范围内分辨真身,猜错就浪…
实战应用:用在哪里 组队邀请、行会宣战这类关键信令丢了没有兜底,玩家只能反复手点,高峰期体验很差。重试机制给信令加确认回执:…
实战应用:用在哪里 新资料片上线首日预约量常是日常十倍,一口气全开会让数据库与登录网关同时过载。滚动开区把开区动作排成队列:…
实战应用:用在哪里 百人同屏的沙巴克外围战场,每个玩家每秒跑动会触发数次位置更新,全部即时下发时广播量随人数平方增长,网关先…