之前由于一直使用 2.0.2 而且也用得挺顺畅,一般不会出什么问题.
我之前的decode具体实现写法如下:
int packageLen = buf.getInt();
int realityLen = buf.remaining();
if (realityLen < packageLen) {
Log.error(".....");
return false;
}
这个写法,我没有在return前把position重置回去. 但是服务器跑得很好, 也从来没发生过黏包现象.
后来接手了一个新项目,发现项目里用的mina组件是2.0.4的.
他的decode写法如下:
// 前面一堆read. 从arg1里read了不少数据了.
if (arg1.remaining() < 4) {
arg1.position(position); // 这个地方重置了position.
return false;
}
这个position我当时没在意, 他decode里有几个地方读取了动态包头,会导致低概率的黏包现象.我把这个BUG给改了.
改的时候我同时换上了我之前2.0.2的写法, 去掉了他的postion重置. 结果后来发现只要return false的地方就会黏包.
然后为了解决问题,我不得不给他加上arg1.position(position);
但是由此引发我一个疑惑. 为什么我2.0.2的写法没问题呢(经过海量例子测试过)?
把话铺开一点讲:
同时, 我也找不出必须设置这个position的理由. 因为arg1是你mina底层丢给我的一个副本. 我凭什么非得给你把position位置还原?
你mina给我的仅仅是个副本. 我return一个false给你就是通知你:"我的读取作废,请你自行重置". 这个时候他没有理由非得要position的原始位置才能重置数据呀!!!!!
就算我自己去实现mina的底层, 我也不一定非得让应用层给我position才行. 我把数据丢给他的时候自己记录一个postion, 如果他返回的是true, 我做ture的操作. 如果他返回给我是false.我做false的操作(我自备了positon)
当然, 可能这些东西都可以深入跟踪mina源代码来获得解答. 但是出于讨论的目的... 以及伸手党的惰性... 我就可耻一回.