Skip to content

特定情况下的连接错误 #159

@sharkghost4

Description

@sharkghost4

问题描述:

我正在为我自己和朋友开发一款用于改善网络连接的模组,但游戏在读取协议层数据时遇到问题,我起初以为这是我模组的问题,直到我用日志尝试定位问题时,发现
服务端:

[12:24:04.313] [Main Thread/INFO] [PublicLogger]: [HookBridge/INFO] Detour.ModPacketSend: mod=ImproveGame netId=40 moduleId=30 moduleType=ImproveGame.Packets.NetAutofisher.RollItemRequest toClient=0 ignoreClient=-1 target=100.124.114.125:50762(Anonymous) len=29 head=1D00FA281E0000006D000000001E000000000000404D1F9E|...(....m...........@M..

客户端:

[12:24:04.472] [Main Thread/WARN] [PublicLogger]: [HookBridge/WARN] Detour.HandleModPacket: drop invalid NetIDs packet reason=modCountOutOfRange side=client-reload(single) reload=True whoAmI=256 peer=100.117.85.52:7777(server) length=27 remaining=131067 modCount=7720 firstByte=40 suspect=unknown previewLen=32 previewHex=281E0000006D000000001E000000000000404D1F9E0100000000070052000000|(....m...........@M.........R...

而这个数据来源于ImproveGame/Content/Tiles/TEAutofisher.cs,如果不拦截这个数据,会导致客户端

[13:13:13.114] [Main Thread/INFO] [StatusText]: The server expects Player.MaxBuffs of 0
but this client reports 143.
Some mod is behaving poorly.
[13:13:13.115] [TCP Client Thread/INFO] [Network]: Closing TcpSocket

因为钓鱼机发送的数据破坏了tModLoader/patches/tModLoader/Terraria/ModLoader/ModNet.cs的NetID,导致服务端与客户端无法正确同步模组数据,随后客户端无法正常连接

如何稳定复现:

在多人服务器放一个正在工作的钓鱼机,确保:有液体、非微光、非松露虫鱼饵、有较高钓鱼力与速度加成(提高触发频率)
有一个正在重载模组的连接客户端(需要重载时间稍微长一些触发钓鱼机发送数据的时机)
复现的完整日志文件:

server.bak.log

client.bak.log
关键点位于:

[13:30:18.434] [Main Thread/INFO] [PublicLogger]: [HookBridge/INFO] Detour.ModPacketSend: mod=CalamityMod netId=3 moduleId=n/a moduleType=n/a toClient=-1 ignoreClient=-1 target=broadcast[] len=19 head=1300FA03153100000085895E00000000008A0C|.....1.....^.......
[13:30:18.927] [Main Thread/INFO] [PublicLogger]: [HookBridge/INFO] Detour.ModPacketSend: mod=ImproveGame netId=40 moduleId=30 moduleType=ImproveGame.Packets.NetAutofisher.RollItemRequest toClient=0 ignoreClient=-1 target=100.124.114.125:56940(Anonymous) len=29 head=1D00FA281E0000006C000000001E000000000000404D1F9E|...(....l...........@M..
[13:30:19.513] [Main Thread/INFO] [PublicLogger]: [HookBridge/INFO] Detour.ModPacketSend: mod=MagicStorage netId=43 moduleId=n/a moduleType=n/a toClient=-1 ignoreClient=-1 target=broadcast[] len=12 head=0C00FA2B038910AB01000001|...+........
[13:30:20.257] [Main Thread/INFO] [PublicLogger]: [HookBridge/INFO] Detour.ModPacketSend: mod=CalamityMod netId=3 moduleId=n/a moduleType=n/a toClient=-1 ignoreClient=-1 target=broadcast[] len=19 head=1300FA03153200000001865E0000000000BF11|.....2.....^.......
[13:30:20.506] [Main Thread/INFO] [PublicLogger]: [HookBridge/INFO] Detour.ModPacketSend: mod=ImproveGame netId=40 moduleId=30 moduleType=ImproveGame.Packets.NetAutofisher.RollItemRequest toClient=0 ignoreClient=-1 target=100.124.114.125:56940(Anonymous) len=29 head=1D00FA281E0000006C000000001E000000000000404D1F9E|...(....l...........@M..
[13:30:21.885] [Main Thread/INFO] [PublicLogger]: [HookBridge/INFO] Detour.ModPacketSend: mod=ImproveGame netId=40 moduleId=30 moduleType=ImproveGame.Packets.NetAutofisher.RollItemRequest toClient=0 ignoreClient=-1 target=100.124.114.125:56940(Anonymous) len=29 head=1D00FA281E0000006C000000001E000000000000404D1F9E|...(....l...........@M..
[13:30:22.488] [Main Thread/INFO] [PublicLogger]: [HookBridge/INFO] Detour.ModPacketSend: mod=ImproveGame netId=40 moduleId=58 moduleType=ImproveGame.Packets.WorldFeatures.BaitlessAutofisherSyncPacket toClient=-1 ignoreClient=-1 target=broadcast[] len=20 head=1400FA283A00000002000000A5149601D700A201|...(:...............
[13:30:22.638] [Server Loop Thread/INFO] [Network]: [0][100.124.114.125:56940 (Anonymous)] Terminating: Connection lost
[13:30:22.642] [Server Loop Thread/INFO] [Network]: [0][100.124.114.125:56940 (Anonymous)] Closing TcpSocket

客户端:

13:30:19.726] [.NET TP Worker/INFO] [tML]: 查找模组……
[13:30:19.727] [.NET TP Worker/INFO] [tML]: Enabling Mod: Daybreak
[13:30:20.024] [Main Thread/DEBUG] [tML]: Assembly Resolve: System.Reflection.Metadata, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a -> System.Reflection.Metadata.resources, Version=8.0.0.0, Culture=zh-Hans, PublicKeyToken=b03f5f7f11d50a3a
[13:30:20.024] [Main Thread/DEBUG] [tML]: Assembly Resolve: System.Reflection.Metadata, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a -> System.Reflection.Metadata.resources, Version=8.0.0.0, Culture=zh, PublicKeyToken=b03f5f7f11d50a3a
[13:30:20.025] [Main Thread/WARN] [tML]: 静默捕获异常: 
System.IO.EndOfStreamException: Unable to read beyond the end of the stream.
   at System.IO.BinaryReader.ReadString()
   at Terraria.ModLoader.ModNet.ReadNetIDs(BinaryReader reader) in tModLoader\Terraria\ModLoader\ModNet.cs:line 608
   at Terraria.ModLoader.ModNet.HandleModPacket(BinaryReader reader, Int32 whoAmI, Int32 length) in tModLoader\Terraria\ModLoader\ModNet.cs:line 632
   at Terraria.MessageBuffer.GetData(Int32 start, Int32 length, Int32& messageType) in tModLoader\Terraria\MessageBuffer.cs:line 3882
   at Terraria.NetMessage.CheckBytes(Int32 bufferIndex) in tModLoader\Terraria\NetMessage.cs:line 2367
   at Terraria.Main.DoUpdate(GameTime& gameTime) in tModLoader\Terraria\Main.cs:line 14455
   at Terraria.Main.Update(GameTime gameTime) in tModLoader\Terraria\Main.cs:line 14354
   at Microsoft.Xna.Framework.Game.Tick() in D:\a\tModLoader\tModLoader\FNA\src\Game.cs:line 546
   at Microsoft.Xna.Framework.Game.RunLoop() in D:\a\tModLoader\tModLoader\FNA\src\Game.cs:line 878
   at Microsoft.Xna.Framework.Game.Run() in D:\a\tModLoader\tModLoader\FNA\src\Game.cs:line 419
   at Terraria.Program.RunGame() in tModLoader\Terraria\Program.cs:line 266
   at Terraria.Program.LaunchGame_(Boolean isServer) in tModLoader\Terraria\Program.cs:line 240
   at Terraria.Program.LaunchGame(String[] args, Boolean monoArgs) in tModLoader\Terraria\Program.cs:line 213
   at Terraria.MonoLaunch.Main_End(String[] args) in tModLoader\Terraria\MonoLaunch.cs:line 79
   at Terraria.MonoLaunch.<>c__DisplayClass1_0.<Main>b__1() in tModLoader\Terraria\MonoLaunch.cs:line 65

[13:30:20.026] [Main Thread/ERROR] [Network]: Unknown(250)
System.IO.EndOfStreamException: Unable to read beyond the end of the stream.
   at System.IO.BinaryReader.ReadString()
   at Terraria.ModLoader.ModNet.ReadNetIDs(BinaryReader reader) in tModLoader\Terraria\ModLoader\ModNet.cs:line 608
   at Terraria.ModLoader.ModNet.HandleModPacket(BinaryReader reader, Int32 whoAmI, Int32 length) in tModLoader\Terraria\ModLoader\ModNet.cs:line 632
   at Terraria.MessageBuffer.GetData(Int32 start, Int32 length, Int32& messageType) in tModLoader\Terraria\MessageBuffer.cs:line 3882
   at Terraria.NetMessage.CheckBytes(Int32 bufferIndex) in tModLoader\Terraria\NetMessage.cs:line 2367
[13:30:20.850] [Main Thread/WARN] [tML]: 静默捕获异常: 
System.FormatException: Too many bytes in what should have been a 7-bit encoded integer.
   at System.IO.BinaryReader.Read7BitEncodedInt()
   at System.IO.BinaryReader.ReadString()
   at Terraria.ModLoader.ModNet.ReadNetIDs(BinaryReader reader) in tModLoader\Terraria\ModLoader\ModNet.cs:line 608
   at Terraria.ModLoader.ModNet.HandleModPacket(BinaryReader reader, Int32 whoAmI, Int32 length) in tModLoader\Terraria\ModLoader\ModNet.cs:line 632
   at Terraria.MessageBuffer.GetData(Int32 start, Int32 length, Int32& messageType) in tModLoader\Terraria\MessageBuffer.cs:line 3882
   at Terraria.NetMessage.CheckBytes(Int32 bufferIndex) in tModLoader\Terraria\NetMessage.cs:line 2367
   at Terraria.Main.DoUpdate(GameTime& gameTime) in tModLoader\Terraria\Main.cs:line 14455
   at Terraria.Main.Update(GameTime gameTime) in tModLoader\Terraria\Main.cs:line 14354
   at Microsoft.Xna.Framework.Game.Tick() in D:\a\tModLoader\tModLoader\FNA\src\Game.cs:line 546
   at Microsoft.Xna.Framework.Game.RunLoop() in D:\a\tModLoader\tModLoader\FNA\src\Game.cs:line 878
   at Microsoft.Xna.Framework.Game.Run() in D:\a\tModLoader\tModLoader\FNA\src\Game.cs:line 419
   at Terraria.Program.RunGame() in tModLoader\Terraria\Program.cs:line 266
   at Terraria.Program.LaunchGame_(Boolean isServer) in tModLoader\Terraria\Program.cs:line 240
   at Terraria.Program.LaunchGame(String[] args, Boolean monoArgs) in tModLoader\Terraria\Program.cs:line 213
   at Terraria.MonoLaunch.Main_End(String[] args) in tModLoader\Terraria\MonoLaunch.cs:line 79
   at Terraria.MonoLaunch.<>c__DisplayClass1_0.<Main>b__1() in tModLoader\Terraria\MonoLaunch.cs:line 65

[13:30:20.850] [Main Thread/ERROR] [Network]: Unknown(250)
System.FormatException: Too many bytes in what should have been a 7-bit encoded integer.
   at System.IO.BinaryReader.Read7BitEncodedInt()
   at System.IO.BinaryReader.ReadString()
   at Terraria.ModLoader.ModNet.ReadNetIDs(BinaryReader reader) in tModLoader\Terraria\ModLoader\ModNet.cs:line 608
   at Terraria.ModLoader.ModNet.HandleModPacket(BinaryReader reader, Int32 whoAmI, Int32 length) in tModLoader\Terraria\ModLoader\ModNet.cs:line 632
   at Terraria.MessageBuffer.GetData(Int32 start, Int32 length, Int32& messageType) in tModLoader\Terraria\MessageBuffer.cs:line 3882
   at Terraria.NetMessage.CheckBytes(Int32 bufferIndex) in tModLoader\Terraria\NetMessage.cs:line 2367

会不会是给出日志中其它模组的问题?

并不是,因为给出的关键点中,其它模组发送的是广播消息,而广播中并不包含正在重载模组的客户端,而ImproveGame直接发送到了100.124.114.125:56940(Anonymous)也就是还未进入到世界当中的客户端,导致tML状态机被破坏从而引发一系列异常,最后客户端强制断开连接。在我查看到ImproveGame\Packets\NetAutofisher\RollItemRequest.cs中的summary时,发现提到

/// <summary>
/// 服务器发送给任意连接的客户端,询问钓鱼机“假人”所处环境
/// Player.UpdateBiomes本应是客户端执行的代码,不应该放到服务器运行
/// </summary>

也许给任意连接的客户端发送消息是很糟糕的行为

如何尝试修复?

请使用Main.ActivePlayers而不是Main.player来获取活跃客户端

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions