377 字
2 分钟
解决通信中的粘包和分包问题

byte[] tempbuffer = new byte[1024 * 1024]; // 缓冲区:收到的字节全攒这里

int templen; // 写指针:缓冲区有效数据的末尾

int nowindex; // 读指针:解析到哪了

public void HandResMeg(byte[] buffer, ref int offset)

{

// ① 收多少存多少:永远追加到已有数据的末尾(templen),不能写 nowindex 位置
buffer.CopyTo(tempbuffer, templen);
templen += buffer.Length;
while (true)
{
// ② 连 8 字节头都没凑齐 → 等下一批数据
if (templen - nowindex < 8) break;
if (templen - nowindex >= 8) // (恒真,可删,只是保险)
{
// ③ 只读头,不推进 nowindex:第 2 个 int 用 nowindex+4 偏移读出来
id = BitConverter.ToInt32(tempbuffer, nowindex);
len = BitConverter.ToInt32(tempbuffer, nowindex + 4);
}
// ④ 整包(8 头 + len 体)没凑齐 → break 等下一批;此时 nowindex 一个字节都没动
if (templen - nowindex < 8 + len) break;
// ⑤ 确认整包齐了,才真正消费头:指针前进 8
nowindex += 8;
if (templen - nowindex >= len) // (恒真,可删)
{
switch (id)
{
case 1111:
// ⑥ 反序列化 body:Reading 读多少推进多少,正好走完 len 个字节
Playerinfo info = new Playerinfo();
info.Reading(tempbuffer, ref nowindex);
Debug.Log($"ID: {info.playerid}, Name: {info.playerdata.name}, Atk: {info.playerdata.atk}");
break;
default:
// ⑦ 没写 case 的协议号:跳过它的 body,否则指针不动 → while 死循环
nowindex += len;
break;
}
continue; // ⑧ 回到循环顶:继续看缓冲区里还有没有下一个整包(粘包在这里被逐个切开)
}
}
// ⑨ 全部消费完才归零;有半包残留时保持现场,等下一批拼上(分包靠它)
if (nowindex == templen)
{
nowindex = 0;
templen = 0;
}

}

解决通信中的粘包和分包问题
https://jinshuangyan.top/posts/unity-tcp-sticky-packet/
作者
烬霜言
发布于
2026-10-11
许可协议
CC BY-NC-SA 4.0

分享文章

生成精美分享图或复制链接,与更多人分享本文。

继续阅读

沿着主题读

基于共同的标签与分类