Skip to content

Commit 6165c42

Browse files
author
purchaseDream
committed
修复客户端 Bundle 发送数据出错,导致服务器收到错误的 msgID,将玩家踢下线的问题。
复现方法: 在地图内(1,1)-(800,800)范围内配置20000个实体,人物 aoiRadius设置为200,aoiRadius 每秒增加 10,人物在游戏中移动,过段时间便会掉线 问题具体代码分析: 1. 服务器发送 onUpdatePropertys(消息体:78字节) 和 onEntityEnterWorld(消息体:6字节) 给客户端 2. 客户端 PacketReceiver 的缓冲区里收到了消息 onUpdatePropertys 的全部和 onEntityEnterWorld 的部分长度(假设收到的 msglen=3) 3. onUpdatePropertys 收到后,根据 eid 找不到实体,从内存池中拿一个 MemoryStream (记为 propMemoryStream )将收到的消息内容拷贝至该 propMemoryStream 中(此时 wpos=78),并插入 _bufferedCreateEntityMessage 4. 处理到 onEntityEnterWorld 时候,发现消息没收全,于是 break 掉,跳出函数 PacketReceiver::process(), 走到 KBEngineApp::sendTick() 函数 5. sendTick() 中 调用 Bundle::newMessage() 时 Bundle 里的 MemoryStream 刚好是 propMemoryStream,于是从 wpos = 78 的地方开始写消息ID,长度,内容;最后 packetSender 发送的时候从 wpos=0 开始发送数据,导致服务器收到的 msgID 是乱的,将 pChannel->condemn(), 客户端掉线 为何 Bundle::newMessage() 里的 MemoryStream 是被 onUpdatePropertys 用过的呢? 1. Bundle::send() 时候先调用 fini(true), fini 函数从池子里取出来一个新的 MemoryStream 2. 再遍历 streamList, 但此时又将 stream 赋值为 streamList[i](此步骤是错误的根源) 3. 遍历 streamList,将旧的 MemoryStream 还给内存池,此时 onUpdatePropertys 从内存池刚好取到 Bundle 还的 MemoryStream,但 Bundle 还在继续使用该 MemoryStream.
1 parent 17736a5 commit 6165c42

File tree

1 file changed

+4
-15
lines changed

1 file changed

+4
-15
lines changed

Bundle.cs

Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
*/
1313
public class Bundle : ObjectPool<Bundle>
1414
{
15-
public MemoryStream stream = new MemoryStream();
15+
public MemoryStream stream = MemoryStream.createObject();
1616
public List<MemoryStream> streamList = new List<MemoryStream>();
1717
public int numMessage = 0;
1818
public int messageLength = 0;
@@ -23,22 +23,11 @@ public Bundle()
2323
{
2424
}
2525

26-
public void clear()
27-
{
28-
stream = MemoryStream.createObject();
29-
streamList = new List<MemoryStream>();
30-
numMessage = 0;
31-
messageLength = 0;
32-
msgtype = null;
33-
_curMsgStreamIndex = 0;
34-
}
35-
3626
/// <summary>
3727
/// 把自己放回缓冲池
3828
/// </summary>
3929
public void reclaimObject()
40-
{
41-
clear();
30+
{
4231
reclaimObject(this);
4332
}
4433

@@ -101,8 +90,8 @@ public void send(NetworkInterface networkInterface)
10190
{
10291
for(int i=0; i<streamList.Count; i++)
10392
{
104-
stream = streamList[i];
105-
networkInterface.send(stream);
93+
MemoryStream tempStream = streamList[i];
94+
networkInterface.send(tempStream);
10695
}
10796
}
10897
else

0 commit comments

Comments
 (0)