hanwentan 2012-04-18
背景:使用mina进行socket编程,而传输数据大小会出现比较大的变化时,出现的BufferUnderflowException问题。
异常如下所示:
org.apache.mina.filter.codec.ProtocolDecoderException: org.apache.mina.core.buffer.BufferDataException: java.io.UTFDataFormatException (Hexdump: 00 00 73 72 01 00 13 6A 61 76 61 2E 75 74 69 6C 2E 41 72 72 61 79 4C 69 73 74 78 70 00 00 00 07 77 04 00 00 00 0A 73 71 00 7E 00 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 15 C9 00 00 00 00 00 00 00 6D 00 00 00 B8 00 00 00 00 00 00 00 00 00 00 00 C8 00 00 00 00 00 00 00 00 70 70 74 00 36 68 74 74 70 3A 2F 2F 6D 2E 62 61 69 64 75 2E 63 6F 6D 2F 73 74 61 74 69 63 2F 69 6E 64 65 78 2F 66 61 76 69 63 6F 6E 2D 35 37 2E 70 6E 67 3F 74 6A 3D 69 63 6F 6E 73 71 00 7E 00 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 3E 00 00 00 00 00 00 00 00 00 00 00 03 A1 00 00 00 00 00 00 00 00 00 00 00 A7 00 00 00 00 00 00 00 10 00 00 00 C8 00 00 00 00 00 00 00 00 70 70 74 00 25 68 74 74 70 3A 2F 2F 6D 2E 62 61 69 64 75 2E 63 6F 6D 2F 73 74 61 74 69 63 2F 69 6E 64 65 78 2F 69 2E 67 69 66 73 71 00 7E 00 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 4E 00 00 00 00 00 00 00 00 00 00 00 00 98 00 00 00 00 00 00 00 00 00 00 00 A6 00 00 00 00 00 00 00 00 00 00 00 C8 00 00 00 00 00 00 00 00 70 70 74 00 24 68 74 74 70 3A 2F 2F 6D 2E 62 61 69 64 75 2E 63 6F 6D 2F 73 74 61 74 69 63 2F 68 62 2F 68 6F 74 2E 67 69 66 73 71 00 7E 00 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 4E 00 00 00 00 00 00 00 00 00 00 00 0B E3 00 00 00 00 00 00 00 00 00 00 00 A8 00 00 00 00 00 00 00 00 00 00 00 C8 00 00 00 00 00 00 00 00 70 70 74 00 26 68 74 74 70 3A 2F 2F 6D 2E 62 61 69 64 75 2E 63 6F 6D 2F 73 74 61 74 69 63 2F 69 6E 64 65 78 2F 70 31 2E 70 6E 67 73 71 00 7E 00)
atorg.apache.mina.filter.codec.ProtocolCodecFilter.messageReceived(ProtocolCodecFilter.java:251)
atorg.apache.mina.core.filterchain.DefaultIoFilterChain.callNextMessageReceived(DefaultIoFilterChain.java:434)
atorg.apache.mina.core.filterchain.DefaultIoFilterChain.access$1200(DefaultIoFilterChain.java:46)
atorg.apache.mina.core.filterchain.DefaultIoFilterChain$EntryImpl$1.messageReceived(DefaultIoFilterChain.java:796)
atorg.apache.mina.filter.logging.LoggingFilter.messageReceived(LoggingFilter.java:177)
atorg.apache.mina.core.filterchain.DefaultIoFilterChain.callNextMessageReceived(DefaultIoFilterChain.java:434)
atorg.apache.mina.core.filterchain.DefaultIoFilterChain.access$1200(DefaultIoFilterChain.java:46)
atorg.apache.mina.core.filterchain.DefaultIoFilterChain$EntryImpl$1.messageReceived(DefaultIoFilterChain.java:796)
atorg.apache.mina.core.filterchain.IoFilterEvent.fire(IoFilterEvent.java:75)
atorg.apache.mina.core.session.IoEvent.run(IoEvent.java:63)
atjava.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
atjava.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
atjava.lang.Thread.run(Thread.java:662)
原因:mina框架生成TransportMetadata对象时,DefaultTransportMetadata的构造方法中有一个参数为fragmentation,boolean类型,分片标志。当设置为true时,会出现分包情况。而在未通过断包与粘包处理情况下,由于分包,最后数据不完整,从而导致异常。
框架处理原理分析:可以根据实际情况,设置buffersize的大小,让buffersize处在平均略高的状态下工作,节省由于初始设置过大,而浪费内存。
解决方案:
1,最简单的修改框架原码。将其中的NioSocketSession类重写即可,里面有TransportMetadata创建的地方修改。
2,通过对断包或粘包的处理。(网上已有相关的博客:http://blianchen.blog.163.com/blog/static/1310562992010101891522100/)