数据封包、拚包时遇到的一个简单的问题 ...

13 views
Skip to first unread message

closeall

unread,
Mar 1, 2006, 9:27:28 PM3/1/06
to dev4s...@googlegroups.com
to all:
 
   数据包的基本格式是:前两个字节为逻辑包的大小 + 数据包的类型 + 数据包的内容。
 
   问题是:在正常情况下,包的前两个字节是逻辑包的大小。 但是假如我到了一个数据包,数据包的内容是 "abc". 这个包的前两个字节并不是正常逻辑包的大小信息,在这种情况下,我应该如何判断包的前两个字节是否表示的是逻辑包的大小信息?

Ghost Cheng

unread,
Mar 1, 2006, 9:32:10 PM3/1/06
to dev4s...@googlegroups.com
Hi closeall :
 
象这样格式的数据报,通常需要定义一个包尾标志,最少2字节,
根据开头的数据包长度,找到包尾,比较包尾是否是预定的值,true则数据包正确。

 
On 3/2/06, closeall <closea...@gmail.com> wrote:
to all:
 
   数据包的基本格式是:前两个字节为逻辑包的大小 + 数据包的类型 + 数据包的内容。
 





--

Sincerely,
Ghost Cheng
Email : ghost...@gmail.com
Web : http://www.GhostSoft.net

BrillyWu

unread,
Mar 1, 2006, 9:33:16 PM3/1/06
to dev4s...@googlegroups.com

如果是TCP连接的话,TCP会保证数据的可靠性,每次收包都根据长度分包,就不会出现错误。出现"ab"的情况,绝对是程序逻辑问题。

可以考虑同步头校验尾的形式,对于TCP来说,徒增一次重复劳动而已。


BrillyWu

unread,
Mar 1, 2006, 9:36:28 PM3/1/06
to dev4s...@googlegroups.com
少考虑了客户端故意发送错误包的情况:(

closeall

unread,
Mar 1, 2006, 9:39:10 PM3/1/06
to dev4s...@googlegroups.com
to BrillyWu :
 
   我的意思是说如果是恶意攻击呢?我刚才写了一个很简单的测试程序,测试程序向服务器发送 "abc"这样的信息,偶然间发现了这个问题。当然我的数据包还没有加密。

 
在06-3-2,BrillyWu <bril...@gmail.com> 写道:

Ghost Cheng

unread,
Mar 1, 2006, 9:40:11 PM3/1/06
to dev4s...@googlegroups.com
Hi closeall :
 
按我说的,加上包尾的检测就行了,去试试吧。

 
On 3/2/06, closeall <closea...@gmail.com> wrote:

大宝(sodme)

unread,
Mar 1, 2006, 9:46:29 PM3/1/06
to dev4s...@googlegroups.com
不用再另外加包尾标志, 有逻辑包长度信息, 就已经暗含结尾是在何处. 反过来说, 即使你加了这个结尾标志,
我还是可以给你设计一个非法的结尾标志, 所以, 增加结尾标志没有任何意义.

这种情况下, 只能根据你收到的逻辑包大小来收剩下的内容, 由于TCP流传输的特点, 你没法判定后面还会不会给你发剩下的包, 所以,
接收操作是比较被动的, 尽管这个内容可能并不是你想的合法的内容. 而这个包的具体格式和数据内容到底非法还是合法, 并不由网络层来处理,
交给逻辑层处理会更为合适.

对待恶意攻击, 你的网络底层应该足够强壮, 主要是一些边界值处理好就行了, 比如:当确定的逻辑包长度小于你指定的逻辑包最小长度时,
这个包明显是错误的, 要丢弃或关闭当前连接; 同理, 如果你定义了逻辑包最大长度, 那这个边界值也要检验.
网络层只负责处理这些边界值并负责把属于边界值以内的逻辑包接收下来即可, 具体的包内容判断交给上层去作.


--
Best regards
大宝(sodme)
Msn : sod...@hotmail.com
Email : sodm...@gmail.com

Ghost Cheng

unread,
Mar 1, 2006, 9:50:13 PM3/1/06
to dev4s...@googlegroups.com
Hi 大宝:
有道理,我光想着确定数据包的正确性了,忽略了可以凭最大包长来验证。

 

closeall

unread,
Mar 1, 2006, 9:55:28 PM3/1/06
to dev4s...@googlegroups.com
to sodme :
 
你的意思是说在网络层只需简单的判断包的最大长度和最小长度就可以了。如果出现了一个非法的逻辑包,这个非法逻辑包的检测工作应该交给上层的逻辑处理,是么??/

 
在06-3-2,Ghost Cheng <ghost...@gmail.com> 写道:

BrillyWu

unread,
Mar 1, 2006, 9:58:06 PM3/1/06
to dev4s...@googlegroups.com
大宝(sodme)

无论网络层,逻辑层,这个问题都必须处理。

假设包校验放在网络层,如果有故意攻击的数据包,一样也能让数据成为一个逻辑包上传到逻辑层。

假设在逻辑层处理,根据错误长度得到的逻辑包,最终逻辑层解析出来的含义都是错误的,而逻辑层也没法校验包的正误。

所以只好在逻辑层对每一个解析后的数值进行边界检查?



On 3/2/06, 大宝(sodme) <sodm...@gmail.com> wrote:

Ghost Cheng

unread,
Mar 1, 2006, 10:02:29 PM3/1/06
to dev4s...@googlegroups.com
Hi BrillyWu :
 
逻辑层对每一个解析后的数值进行边界检查是肯定必须的。不过不一定是边界检查,只要是逻辑上正确就行了。
例如client发来一个人物ID(Login时选人),不论这个值是什么,只要这个ID不存在,或这个这个ID不属于这个账号,就是错误的。


 
On 3/2/06, BrillyWu <bril...@gmail.com> wrote:

Li Jie

unread,
Mar 1, 2006, 10:02:55 PM3/1/06
to dev4s...@googlegroups.com
同意。我以前也用过包结束标志,甚至考虑过在包头保存一个CRC,后来发现这实际上是多余的,人家要想攻击你,肯定会去研究你的包,所以只需要验证长度就行了,其它的验证放到逻辑层处理

在 06-3-2,大宝(sodme)<sodm...@gmail.com> 写道:

大宝(sodme)

unread,
Mar 1, 2006, 10:19:19 PM3/1/06
to dev4s...@googlegroups.com
异常分为很多种情况, 比如:

1. 逻辑包大小根本就是一个非法值: 太小且小于最小逻辑包长度比如1或2(总之就是你用来定义逻辑包长度的那个字节数),
太大且大于最大逻辑包长度(拼包算法进行操作时, 可能会用到所谓的拼包缓冲区, 而这个缓冲区如果是静态的,不是new出来的,
你就得预计最大包可能是多大, 超过这个大小的包要进行异常处理)

2. 逻辑包的包类型根本不是游戏所允许的包类型

3. 逻辑包的包类型是允许的包类型, 但包内容却是错误的, 比如一个说话包, 虽然类型也是说话包的包类型,
但说话者ID这个字段的值却是一个根本不存在或根本不在线的玩家, 那这个包也是异常包.

针对于前两种情况, 我们都可以在网络层处理掉, 但针对于第3种情况, 只有在逻辑层去作了,
网络层是没法知道或根本不用知道第3种错误的处理的. 网络层与逻辑层各司其职就OK了.

至于BrillyWu说的在逻辑层也作一次边界检查, 这个, 我不知道指的是什么意思, 如果仅指基于数据格式方面的长度边界检查,
我认为没必要, 因为这个数据是由网络层提交给你逻辑层的, 网络层已经作为这个长度边界检查.
而如果BrillyWu说的是象前面说的"说话包里的说话内容长度"这样类似到具体包内容的字段里所含的长度边界检查, 那逻辑层自然是要作的.

Email : sodm...@gmail.com

Xin Li

unread,
Mar 1, 2006, 10:34:42 PM3/1/06
to dev4s...@googlegroups.com
逻辑包的类型合法性放在逻辑层做比较好吧
权责分明
 

大宝(sodme)

unread,
Mar 1, 2006, 10:38:53 PM3/1/06
to dev4s...@googlegroups.com
嗯, 是, 放在那个查表/查处理函数入口的地方.

Email : sodm...@gmail.com

WL

unread,
Mar 1, 2006, 11:24:59 PM3/1/06
to 高性能网络编程邮件列表
同意这种观点。
网络层只应该负责数据的收发,只要能得到一个完整的逻辑包就没有任何理由将其丢弃。至于这个逻辑包内容是什么,是否合法,这应该由逻辑层负责。

ppmsn2005

unread,
Mar 2, 2006, 12:02:24 AM3/2/06
to dev4s...@googlegroups.com
这个问题遇见过。 我的结论是 如果有故意的错误包 (逻辑层面),只有断线。 试图重新恢复正常 是徒劳的。试图修复一个错误的代价实在太大了

comet123

unread,
Mar 2, 2006, 2:10:22 AM3/2/06
to dev4s...@googlegroups.com
closeall,您好!
 
  根本不要去判断,我觉得,需要做的只是按照(数据包的基本格式)去接受/解析数据,
而你说的情况根本就是一种数据错误,在解包中的错误
 
======== 2006-03-02 10:27:28 您在来信中写道: ========
 
to all:
 
   数据包的基本格式是:前两个字节为逻辑包的大小 + 数据包的类型 + 数据包的内容。
 
   问题是:在正常情况下,包的前两个字节是逻辑包的大小。 但是假如我到了一个数据包,数据包的内容是 "abc".

= = = = = = = = = = = = = = = = = = = = = =

        致
礼!

 
              comet123
              come...@163.com
               2006-03-02
 

sunway

unread,
Mar 2, 2006, 2:47:54 AM3/2/06
to 高性能网络编程邮件列表
关于这个问题,传奇的协议做的非常不错,呵呵,虽然大家都说这个游戏烂。

WL38

unread,
Mar 2, 2006, 3:14:22 AM3/2/06
to 高性能网络编程邮件列表
传奇是怎么做的呢,尝试着修复错误,即使是恶意的非法包?

sunway

unread,
Mar 2, 2006, 3:31:32 AM3/2/06
to 高性能网络编程邮件列表
传奇用的是字符串协议,用分隔符,
先把2进制数据用类BASE64算法处理一下,然后加上分隔符,
这样即使出现错误的包,只要拆包算法写的好,有重新定位
功能,就可以继续收下一个包。

大宝(sodme)

unread,
Mar 2, 2006, 8:19:38 AM3/2/06
to dev4s...@googlegroups.com
重新定位并非难事, 呵呵. 当发现当前包格式有误时, 只要重置拼包缓冲区首指针就可以继续收后面的数据并完成拼装. sunway应该指的是这样的重新定位吧? :)

sunway

unread,
Mar 2, 2006, 10:31:17 AM3/2/06
to 高性能网络编程邮件列表
如果是2进制
协议,里面的长度字段错误后面,而后面恰好没有发全一个包,
那么整个次序就乱了,因为后面发的半个包有可能和下一个包叠在一起,最
坏情况下完全乱掉。
>>重新定位并非难事, 呵呵. 当发现当前包格式有误时, 只要重置拼包缓冲区首指针就可以>>继续收后面的数据并完成拼装. sunway应该指的是这样的重新定位吧? :)

Ghost Cheng

unread,
Mar 2, 2006, 10:47:54 AM3/2/06
to dev4s...@googlegroups.com
Hi All:
同意张无忌的观点,我现在服务器与服务器之间的通讯采用2进制协议,依靠包头的封包长度解包,
而客户端与服务器之间的通讯,采用的是base64编码的方式,通过一个包头字符与一个包尾字符解包。

 
On 3/2/06, sunway <sunh...@gmail.com> wrote:
>>重新定位并非难事, 呵呵. 当发现当前包格式有误时, 只要重置拼包缓冲区首指针就可以>>继续收后面的数据并完成拼装. sunway应该指的是这样的重新定位吧? :) Web : http://www.GhostSoft.net

大宝(sodme)

unread,
Mar 2, 2006, 8:02:51 PM3/2/06
to 高性能网络编程邮件列表
是呀, 那相比之下,
带包对和包尾标志的协议会比只带包长度的协议在重新定位方面表现要好得多,
只带包长度的,
确实如无忌所言容易造成后面的包也连在一起,
而它的重新定位就可能是错了N个包之后的了,
带包头和包尾的却可以只影响当前包, 嗯, 了解了. :)

--
sodme

Li Jie

unread,
Mar 2, 2006, 8:09:45 PM3/2/06
to dev4s...@googlegroups.com
是否真的有必要做这种错误恢复呢?什么情况下才会发生这种错误?

2006/3/3, 大宝(sodme) <sodm...@gmail.com>:

comet123

unread,
Mar 3, 2006, 2:32:24 AM3/3/06
to dev4s...@googlegroups.com
sunway,您好!
"里面的长度字段错误", 是什么意思,有点不明白。
如果是TCP,这种错误引起的原因是什么呢?Client的BUG?或者被恶意程序攻击?
对这种情况还需要 “容错”和“修复”处理吗?或者是直接断开?
有点糊涂了,~


======= 2006-03-02 23:31:17 您在来信中写道:=======

>如果是2进制
>协议,里面的长度字段错误后面,而后面恰好没有发全一个包,
>那么整个次序就乱了,因为后面发的半个包有可能和下一个包叠在一起,最
>坏情况下完全乱掉。
>>>重新定位并非难事, 呵呵. 当发现当前包格式有误时, 只要重置拼包缓冲区首指针就可以>>继续收后面的数据并完成拼装. sunway应该指的是这样的重新定位吧? :)
>
>

= = = = = = = = = = = = = = = = = = = =


        致
礼!


        comet123
        come...@163.com
          2006-03-03

WL38

unread,
Mar 3, 2006, 6:09:06 AM3/3/06
to 高性能网络编程邮件列表
我觉得对于这种情况直接断开就是了,没有必要尝试恢复的。不过最好能记录下出错的数据、请求的IP、时间、等等其他上下文数据,方便以后分析是恶意分析还是客户端的
Bug。

疯子阿虹

unread,
Mar 6, 2006, 5:31:34 AM3/6/06
to 高性能网络编程邮件列表
是的,是应该交给逻辑层,网络层仅仅是一个功能库,toolkit,它不可能去判断每一个包的合法性:(
可以在客户端给每一个包进行编号,依次递增,这样可以在网络层简单的进行判断,并且可以简单的防治外挂。
当然也可以加crc进行效验,不过没有测试过:)

WL38

unread,
Mar 13, 2006, 2:12:10 AM3/13/06
to 高性能网络编程邮件列表
对于二进制协议来说的话,实在不明白包尾的意义所在。包内容里面可以出现包尾标志吗,如果可以的话,就算可以找到这个标志,也不能说明这个就是包尾标志。
Reply all
Reply to author
Forward
0 new messages