lvzixun / sproto-Csharp

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

rpc.spack.pack有可能问题 #1

Closed xcarray closed 9 years ago

xcarray commented 9 years ago

SprotoRpc.cs line(55) rpc.spack.pack 返回的bytes与sproto.lua pack返回的bytes有时会不一致。 协议定义:

game_c2s_login 1000 {
    request {
        user_uid    0 : string                      # username
        token       1 : string                  # token
        version     2 : string                      # 客户端版本
        channel     3 : integer             # 哪个渠道
        zone        4 : integer             # 哪个区
        channel_username 5 : string                 # [数据分析][客服查询]用户在渠道那边的用户名
    }
    response {
        errno       0 : integer             #
        time        1 : integer             # 服务器本地时间,1970到现在的秒(北京/重庆/上海时间+8区)
        role_num    2 : integer                 # 角色数量(为零时 需要创建角色)
    }
}

测试用例: 1 { user_uid = "xxxxx", token = "1"} csharp编码pack之后与lua库输出是一致的 2 { user_uid = "xxxxx", token = "abc123"}csharp编码与lua输出是一致的,但是经过pack之后就不一致了。

lvzixun commented 9 years ago

能否提供下测试数据?

xcarray notifications@github.com于2015年7月2日 周四上午11:57写道:

SprotoRpc.cs line(55) rpc.spack.pack 返回的bytes与sproto.lua pack返回的bytes有时会不一致。 协议定义: 登陆

game_c2s_login 1000 { request { user_uid 0 : string # username token 1 : string # token version 2 : string # 客户端版本 channel 3 : integer # 哪个渠道 zone 4 : integer # 哪个区 channel_username 5 : string # [数据分析][客服查询]用户在渠道那边的用户名 } response { errno 0 : integer # time 1 : integer # 服务器本地时间,1970到现在的秒(北京/重庆/上海时间+8区) role_num 2 : integer # 角色数量(为零时 需要创建角色) } }

— Reply to this email directly or view it on GitHub https://github.com/lvzixun/sproto-Csharp/issues/1.

xcarray commented 9 years ago

我们客户端是的是您的解析,服务端用的lua的解析,上例那个协议不进行pack是不会出解析问题的,token="1"时pack也不会出错,为其它数据时,就会出现lua解析出错,我dump了两边的数据,发现csharp的结果和lua库的结果不一致。我还没有去调试,现在是先采用的nopack模式在运行。

xcarray commented 9 years ago

sproto lua的解析是用的云风的最新版本。

lvzixun commented 9 years ago

能否提供下encode生成的二进制数据(未pack前的)?

刚才我测试了下,pack之后跟lua是一致的。测试的代码大致如下:

SprotoType.game_c2s_login.request t1 = new SprotoType.game_c2s_login.request();
t1.user_uid = "xxxxx";
t1.token = "abc123";
byte[] rt1 = clientRequest.Invoke<Protocol.game_c2s_login> (t1, 1);
assert (rt1, new byte[]{
  0X5D, 0X02, 0XD2, 0X07, 0X04, 0X02, 0X10, 0X05, 0X3F, 0X78,
  0X78, 0X78, 0X78, 0X78, 0X06, 0X7E, 0X61, 0X62, 0X63, 0X31,
  0X32, 0X33,
});
xcarray commented 9 years ago

请试试这个例子:

...
t1.token = "83d4555b0a19063ccbdf14348f7ba39f";
...

pack前dump的都是:

02 00 D2 07 04 00 02 00 01 00 00 00 20 00 00 00 38 33 64 34 35 35 35 62 30 61 31 39 30 36 33 63 63 62 64 66 31 34 33 34 38 66 37 62 61 33 39 66

cs pack之后:

5D 02 D2 07 04 02 11 01 20 FF 0D 38 33 64 34 35 35 35 62 30 61 31 39 30 36 33 63 63 62 64 66 31 34 33 34 38 66 37 62 61 33 39 66

lua pack之后:

5D 02 D2 07 04 02 11 01 20 FF 03 38 33 64 34 35 35 35 62 30 61 31 39 30 36 33 63 63 62 64 66 31 34 33 34 38 66 37 62 61 33 39 66

差别在:

cs:byte[0x0a]=0x0d
lua:byte[0x0a]=0x03
xcarray commented 9 years ago

lua:测试

local dump = '02 00 D2 07 04 00 02 00 01 00 00 00 20 00 00 00 38 33 64 34 35 35 35 62 30 61 31 39 30 36 33 63 63 62 64 66 31 34 33 34 38 66 37 62 61 33 39 66'
print('data:')
local data = antidump(dump)
print(dumpbyte(data))
local packed = sprot_core.pack(data)
print('packed:')
print(dumpbyte(packed))

输出:

data:
02 00 D2 07 04 00 02 00 01 00 00 00 20 00 00 00 38 33 64 34 35 35 35 62 30 61 31 39 30 36 33 63 63 62 64 66 31 34 33 34 38 66 37 62 61 33 39 66 
packed:
5D 02 D2 07 04 02 11 01 20 FF 03 38 33 64 34 35 35 35 62 30 61 31 39 30 36 33 63 63 62 64 66 31 34 33 34 38 66 37 62 61 33 39 66 
lvzixun commented 9 years ago

我在我自己的mac上面测试,竟然是没问题的. Orz 我在TestCaseSprotoPack.cs中加了一段做测试:

byte[] data2 = new byte[] {
  0X02, 0X00, 0XD2, 0X07, 0X04, 0X00, 0X02, 0X00, 0X01, 0X00,
  0X00, 0X00, 0X20, 0X00, 0X00, 0X00, 0X38, 0X33, 0X64, 0X34,
  0X35, 0X35, 0X35, 0X62, 0X30, 0X61, 0X31, 0X39, 0X30, 0X36,
  0X33, 0X63, 0X63, 0X62, 0X64, 0X66, 0X31, 0X34, 0X33, 0X34,
  0X38, 0X66, 0X37, 0X62, 0X61, 0X33, 0X39, 0X66,
};

Console.WriteLine ("======pack=======");

byte[] pack_data1 = extract.pack (data2);
dump_bytes (pack_data1);
assert (pack_data1, new byte[] {
  0X5D, 0X02, 0XD2, 0X07, 0X04, 0X02, 0X11, 0X01, 0X20, 0XFF,
  0X03, 0X38, 0X33, 0X64, 0X34, 0X35, 0X35, 0X35, 0X62, 0X30,
  0X61, 0X31, 0X39, 0X30, 0X36, 0X33, 0X63, 0X63, 0X62, 0X64,
  0X66, 0X31, 0X34, 0X33, 0X34, 0X38, 0X66, 0X37, 0X62, 0X61,
  0X33, 0X39, 0X66,
});

你用的环境是什么样子的?

xcarray commented 9 years ago

客户端是在windows下的。我的lua测试是在mac上做的。 我也在mac上用cs做个测试看

lvzixun commented 9 years ago

写入错误的地方是在 : https://github.com/lvzixun/sproto-Csharp/blob/master/src/SprotoPack.cs#L24

this.buffer.WriteByte (0xff);
this.buffer.WriteByte ((byte)(align8_n/8 - 1));  // write error: 0X0D

从调用栈里面看到是从125行this.write_ff (ff_src, ff_srcstart, ff_desstart, ff_src.Length - ff_srcstart); 最后的参数n在window上面貌似写的是错的。你那边有调试环境吗? 可以下个断点看下~ ;)

xcarray commented 9 years ago

好的。我这边调试一下。

lvzixun commented 9 years ago

我这边打印的的的write_ff参数

 Sproto.SprotoPack.write_ff (src={byte[48]}, offset=16, pos=9, n=32) in /Users/zixunlv/codes/sproto-Csharp/src/SprotoPack.cs:23
xcarray commented 9 years ago

SprotoPack.pack函数有问题 测试用例稍改一下就会出错

SprotoPack extract = new SprotoPack();

        byte[] data2 = new byte[] {
          0X02, 0X00, 0XD2, 0X07, 0X04, 0X00, 0X02, 0X00,   
          0X01, 0X00, 0X00, 0X00, 0X20, 0X00, 0X00, 0X00, 
          0X38, 0X33, 0X64, 0X34, 0X35, 0X35, 0X35, 0X62, 
          0X30, 0X61, 0X31, 0X39, 0X30, 0X36, 0X33, 0X63, 
          0X63, 0X62, 0X64, 0X66, 0X31, 0X34, 0X33, 0X34,
          0X38, 0X66, 0X37, 0X62, 0X61, 0X33, 0X39, 0X66,
          0x11, 0x22,
        };

        Console.WriteLine("======pack=======");

        byte[] pack_data1 = extract.pack(data2, data2.Length - 2);
        dump_bytes(pack_data1);
        assert(pack_data1, new byte[] {
          0X5D, 0X02, 0XD2, 0X07, 0X04, 0X02, 0X11, 0X01, 
          0X20, 0XFF, 0X03, 0X38, 0X33, 0X64, 0X34, 0X35, 
          0X35, 0X35, 0X62, 0X30, 0X61, 0X31, 0X39, 0X30, 
          0X36, 0X33, 0X63, 0X63, 0X62, 0X64, 0X66, 0X31, 
          0X34, 0X33, 0X34, 0X38, 0X66, 0X37, 0X62, 0X61,
          0X33, 0X39, 0X66,
        });

data2原始数据我加了2字节,pack时候data2.Length-2,实际pack还是以前的数据,这个情况下就出错了。

lvzixun commented 9 years ago

bugfix, 我这边测试没问题了。 你review下,如果测试正常的话,就close吧。 ;)

lvzixun commented 9 years ago

之所以会有这个bug是因为我想减少创建临时byte[]对象。所以就添加了一个参数len。但在pack过程中忘记了去取len,而直接用data.length。 Orz

PS: sproto lua版本没有问题是因为没有提供部分pack。

xcarray commented 9 years ago

谢谢了。我测试正常了。