lvzixun / sproto-Csharp

A pure C# implementation of sproto.
140 stars 53 forks source link

fix some bug #5

Closed m2q1n9 closed 8 years ago

m2q1n9 commented 8 years ago

il2cpp bug 比较运算符两边都是动态类型时 会导致il2cpp编译器无法静态做类型推导 SprotoStream相关bug 具体看diff

m2q1n9 commented 8 years ago

现在的那几个判断 构建unity ios版本时 如果开启il2cpp 会编译不过 这个比错误判断问题大多了

lvzixun commented 8 years ago

能否加个macro来判il2cpp是否开启?

m2q1n9 commented 8 years ago

可以判断下是否是ios版本 ios要支持64位一定要开il2cpp的 另外 pack时有时会走到这 偶现 原因未知 https://github.com/lvzixun/sproto-Csharp/blob/master/src/SprotoPack.cs#L130

lvzixun commented 8 years ago

那个异常是说, 对pack的buffer而言, 最坏情况下每2K字节会多浪费2个字节, 这里的maxsz是pack后的最大值。如果pack之后发现大小超过了maxsz将会认为是错误的。

能否提供下对应pack的二进制数据?

m2q1n9 commented 8 years ago

周一过去加点log 出现的概率还挺高 游戏挂在那就会出 有的时候能pack出错误数据 然后发到服务端unpack时会挂 我暂时只是过滤了下~

lvzixun commented 8 years ago

有日志显示SprotoTypeSize.error ("packing error, return size="+this.buffer.Position); 这段代码中的return size是多少吗?

m2q1n9 commented 8 years ago

好像是169

lvzixun commented 8 years ago

我看了下pack的代码,看上去并不会出现这样的问题。 你那边方便把出现异常的buffer给dump出来吗?有必现的测试数据的话,会好查一些。

m2q1n9 commented 8 years ago

https://github.com/lvzixun/sproto-Csharp/blob/master/src/SprotoRpc.cs#L55 从这调过去的 我加些代码把pack前的数据dump下好了 周一上班再搞了 复现还是要看点运气的

m2q1n9 commented 8 years ago

和这行代码有关系么? https://github.com/lvzixun/sproto-Csharp/pull/5/files#diff-27863826e7cf9eb708a95f715e934b12L105

lvzixun commented 8 years ago

pack本身应该跟sprotoStream没关系的。你对sprotoStream的修改我之前也看过,看样子跟pack没关系的。我觉得,先把pack出现异常的buffer dump出来看看再说吧。

m2q1n9 commented 8 years ago

那个错误数据dump出来了 RPC encode后 01 00 ee 4e 01 00 00 00 58 00 00 00 06 00 00 00 00 00 03 00 00 00 03 00 04 00 0a 00 00 00 31 34 35 30 36 37 38 32 36 35 2a 00 00 00 02 00 00 00 00 00 18 00 00 00 03 00 00 00 40 06 00 00 04 00 00 00 c6 73 02 00 04 00 00 00 a8 7e 02 00 04 00 00 00 1d fd 06 00 0a 00 00 00 04 00 d2 07 01 00 fe 17 02 00

pack后 1d 01 ee 4e 01 11 58 06 44 03 03 c5 04 0a 31 34 ff 00 35 30 36 37 38 32 36 35 11 2a 02 44 18 03 4c 40 06 04 5c c6 73 02 04 5c a8 7e 02 04 5c 1d fd 06 0a 74 04 d2 07 01 07 fe 17 02

Dispatch时就会出异常了

lvzixun commented 8 years ago

我在云风的lua版本sproto和sproto-csharp中都测试了下上面你提供的数据, 进行pack后跟你提供的数据是一致的。而且都能正常的unpack.

------ raw ------
01 00 EE 4E 01 00 00 00 - 58 00 00 00 06 00 00 00
00 00 03 00 00 00 03 00 - 04 00 0A 00 00 00 31 34
35 30 36 37 38 32 36 35 - 2A 00 00 00 02 00 00 00
00 00 18 00 00 00 03 00 - 00 00 40 06 00 00 04 00
00 00 C6 73 02 00 04 00 - 00 00 A8 7E 02 00 04 00
00 00 1D FD 06 00 0A 00 - 00 00 04 00 D2 07 01 00
FE 17 02 00
---- pack -----
1D 01 EE 4E 01 11 58 06 - 44 03 03 C5 04 0A 31 34
FF 00 35 30 36 37 38 32 - 36 35 11 2A 02 44 18 03
4C 40 06 04 5C C6 73 02 - 04 5C A8 7E 02 04 5C 1D
FD 06 0A 74 04 D2 07 01 - 07 FE 17 02
---- unpack -----
01 00 EE 4E 01 00 00 00 - 58 00 00 00 06 00 00 00
00 00 03 00 00 00 03 00 - 04 00 0A 00 00 00 31 34
35 30 36 37 38 32 36 35 - 2A 00 00 00 02 00 00 00
00 00 18 00 00 00 03 00 - 00 00 40 06 00 00 04 00
00 00 C6 73 02 00 04 00 - 00 00 A8 7E 02 00 04 00
00 00 1D FD 06 00 0A 00 - 00 00 04 00 D2 07 01 00
FE 17 02 00 00 00 00 00 -

你说的跑出异常是说在客户端pack之后,在服务器那边unpack dispatch 出现了异常?还是说,客户端这边收到服务器返回的这个pack后的数据, 在客户端unpack后dispatch出现了异常?

m2q1n9 commented 8 years ago
        byte[] pack_buffer = rpc.spack.pack(rpc.stream.Buffer, len);

        try
        {
            rpc.Dispatch(pack_buffer);
        } catch (Exception e)
        {
            dump_bytes(rpc.stream.Buffer, len);
            dump_bytes(pack_buffer, pack_buffer.Length);
        }

        return pack_buffer;

改了rpc Invoke return前Dispatch了下

m2q1n9 commented 8 years ago

可以unpack 可能数据不对

lvzixun commented 8 years ago

你不应当在invoke中调用rpc.Dispatch(pack_buffer);, 对于客户端来说invoke的含义是client发送给server数据包, dispatch的含义是分发client接受到server发来的数据包。如果server和client用的协议是两份的话,客户端dispatch到一个客户端不知道的协议(但是服务器是知道的)确实会出现异常。

我觉得添加异常捕获的地方需要修改下: 客户端:你应该是在网络层接收到服务器发来的数据包,进行client.dispatch那里try catch。 服务器:应当在server.dispatch那里进行try catch 捕获出现无法解析的数据包。

m2q1n9 commented 8 years ago

就用一份协议 invoke后的数据 不管发给客户端还是服务端应该都能dispatch解析把? 这个是玩家的状态同步包 服务端验证后会原样同步给场景中的其他客户端

m2q1n9 commented 8 years ago

这个dispatch失败出现的概率不是很高

lvzixun commented 8 years ago

如果是一份的话,确实不论是client还是server都能够正确的dispatch出来。只要你创建client rpc对象的时候有传入protocol:SprotoRpc client = new SprotoRpc (Protocol.Instance);

如果pack,unpack都没问题的话,那有可能是进行decode的时候出现了问题。你那边方便提供下具体协议的定义吗?

lvzixun commented 8 years ago
 byte[] pack_buffer = rpc.spack.pack(rpc.stream.Buffer, len);

        try
        {
            rpc.Dispatch(pack_buffer);
        } catch (Exception e)
        {
            dump_bytes(rpc.stream.Buffer, len);
            dump_bytes(pack_buffer, pack_buffer.Length);
        }

        return pack_buffer;

异常的具体信息能够查看到吗?能否知道是在哪一行出现了问题?

m2q1n9 commented 8 years ago

我把那个数据直接Dispatch下 发现是能解出来的。。

m2q1n9 commented 8 years ago

目前看应该是Dispatch重入了~

lvzixun commented 8 years ago

我觉得你可以尝试把try catch的位置给改下,放到client.dispatch(resp)那里。 服务器那边最好也加个try catch,检查下是否从客户端收到错误的包。

m2q1n9 commented 8 years ago

之前因为一个bug导致两条socket recv线程在跑 recv会调用Dispatch 导致Dispatch可能重入 出现这个问题 改好后send的时候Invoke里加了try Dispatch catch这个反而掉坑了 因为send和recv也是两条线程。。 目前还没完全确认这个问题 暂时把 try Dispatch catch 删了 确保只有1个地方会Dispatch 看还有没问题 :)

lvzixun commented 8 years ago

我先把你的提交mergemaster上面来吧。