- 浏览: 787303 次
- 性别:
- 来自: 深圳
文章分类
最新评论
-
萨琳娜啊:
Java读源码之Netty深入剖析网盘地址:https://p ...
Netty源码学习-FileRegion -
飞天奔月:
写得有趣 ^_^
那一年你定义了一个接口 -
GoldRoger:
第二个方法很好
java-判断一个自然数是否是某个数的平方。当然不能使用开方运算 -
bylijinnan:
<script>alert("close ...
自己动手实现Java Validation -
paul920531:
39行有个bug:"int j=new Random ...
java-蓄水池抽样-要求从N个元素中随机的抽取k个元素,其中N无法确定
看DelimiterBasedFrameDecoder的API,有举例:
接收到的ChannelBuffer如下:
+--------------+ | ABC\nDEF\r\n | +--------------+
经过DelimiterBasedFrameDecoder(Delimiters.lineDelimiter())之后,得到:
+-----+-----+ | ABC | DEF | +-----+-----+
而不是
+----------+ | ABC\nDEF |
为什么 ?
首先要明确,如果不指定,DelimiterBasedFrameDecoder默认会去掉分隔符
其次看看Delimiters.lineDelimiter(),它返回两组delimiter,分别对应windows和linux的换行符
public static ChannelBuffer[] lineDelimiter() { return new ChannelBuffer[] { ChannelBuffers.wrappedBuffer(new byte[] { '\r', '\n' }), ChannelBuffers.wrappedBuffer(new byte[] { '\n' }), }; }
考察这两组分隔符
方案一
采用“\r\n”作为分隔,则返回
frameA = "ABC\nDEF"
方案二
采用“\n”返回
frameB_0 = "ABC"
frameB_1 = "DEF\r"
由于frameB_0的长度比frameA短,因此在这个例子中,会采用方案二
但有个问题,为什么不是比较全部,而是只比较frameB_0?
要知道,length(frameA) = length(frameB_0) + length(frameB_1),两者相等
刚开始,我还以为跟split一样,方案二会一次性返回“ABCDEF\r”
实际上不是
它是遇到一个分隔符,就返回一个结果
可以通过下面的代码证明:
public class ClientHandler extends SimpleChannelUpstreamHandler { @Override public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception { String msg = "ABC\nDEF\r\n"; ChannelBuffer buff = ChannelBuffers.buffer(msg.length()); buff.writeBytes(msg.getBytes()); e.getChannel().write(buff); } }
Server:
bootstrap.setPipelineFactory(new ChannelPipelineFactory() { public ChannelPipeline getPipeline() throws Exception { ChannelPipeline pipeline = Channels.pipeline(); //这里设置:不删除分隔符,方便观察 pipeline.addLast("handler1", new DelimiterBasedFrameDecoder(8192, false, Delimiters.lineDelimiter())); pipeline.addLast("handler2", new ServerStringHandler()); //打印decode后的结果 return pipeline; } });
ServerStringHandler:
public class ServerStringHandler extends SimpleChannelUpstreamHandler{ @Override public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception { ChannelBuffer buff = (ChannelBuffer)e.getMessage(); String msg = (String)buff.toString(Helper.CHARSET_UTF8); //String s = "abc\n"; 则msg_escape 会原样输出“abc\n”,而不是“abc”外加一个换行 String msg_escape = StringEscapeUtils.escapeJava(msg); System.out.println("msg = " + msg_escape); } }
结果ServerStringHandler会分两次输出:
msg = ABC\n msg = DEF\r\n
查看源码,会更清楚:
public class DelimiterBasedFrameDecoder extends FrameDecoder { private final ChannelBuffer[] delimiters; private final int maxFrameLength; /*返回结果中,是否去掉分隔符 通常的调用是去掉分隔符,例如 new DelimiterBasedFrameDecoder(8192, Delimiters.lineDelimiter()) 等价于 new DelimiterBasedFrameDecoder(8192, /*stripDelimiter=*/true, Delimiters.lineDelimiter()) */ private final boolean stripDelimiter; @Override protected Object decode( ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer) throws Exception { // Try all delimiters and choose the delimiter which yields the shortest frame. int minFrameLength = Integer.MAX_VALUE; ChannelBuffer minDelim = null; /*迭代每一个delimiter,都尝试进行decode, 然后选择返回“shortest frame”的那个delimiter 重点在indexOf这个方法 */ for (ChannelBuffer delim: delimiters) { int frameLength = indexOf(buffer, delim); if (frameLength >= 0 && frameLength < minFrameLength) { minFrameLength = frameLength; minDelim = delim; } } if (minDelim != null) { int minDelimLength = minDelim.capacity(); ChannelBuffer frame; if (stripDelimiter) { frame = buffer.readBytes(minFrameLength); buffer.skipBytes(minDelimLength); } else { frame = buffer.readBytes(minFrameLength + minDelimLength); } return frame; } } /* 对frame(haystack)进行搜索,找到第一个delimiter(needle),这个位置记为i 返回 (i - haystack.readerIndex),也就是分隔后第一个sub frame的长度 可以看到,它是“找到一个,就返回一个” */ private static int indexOf(ChannelBuffer haystack, ChannelBuffer needle) { //遍历haystack的每一个字节 for (int i = haystack.readerIndex(); i < haystack.writerIndex(); i ++) { int haystackIndex = i; int needleIndex; /*haystack是否出现了delimiter,注意delimiter是一个ChannelBuffer(byte[]) 例如对于haystack="ABC\r\nDEF",needle="\r\n" 那么当haystackIndex=3时,找到了“\r”,此时needleIndex=0 继续执行循环,haystackIndex++,needleIndex++, 找到了“\n” 至此,整个needle都匹配到了 程序然后执行到if (needleIndex == needle.capacity()),返回结果 */ for (needleIndex = 0; needleIndex < needle.capacity(); needleIndex ++) { if (haystack.getByte(haystackIndex) != needle.getByte(needleIndex)) { break; } else { haystackIndex ++; if (haystackIndex == haystack.writerIndex() && needleIndex != needle.capacity() - 1) { return -1; } } } if (needleIndex == needle.capacity()) { // Found the needle from the haystack! return i - haystack.readerIndex(); } } return -1; } }
发表评论
-
TCP的TIME-WAIT
2014-04-23 16:35 1199原文连接:http://vincent.bernat.im/e ... -
《TCPIP详解卷1》学习-拥塞避免
2014-01-15 15:16 159拥塞避免算法、 ... -
Netty源码学习-HTTP-tunnel
2014-01-14 18:19 4304Netty关于HTTP tunnel的说明: http://d ... -
Netty源码学习-FileRegion
2013-12-31 17:17 5661今天看org.jboss.netty.example.http ... -
Netty源码学习-HttpChunkAggregator-HttpRequestEncoder-HttpResponseDecoder
2013-12-27 16:10 4090今天看Netty如何实现一个Http Server org.j ... -
Netty源码学习-ReadTimeoutHandler
2013-12-26 17:53 3838ReadTimeoutHandler的实现思 ... -
Netty学习笔记
2013-12-25 18:39 1488本文是阅读以下两篇文章时: http://seeallhear ... -
Netty源码学习-ChannelHandler
2013-12-25 18:12 1636一般来说,“有状态”的ChannelHandler不应 ... -
Netty源码学习-ServerBootstrap启动及事件处理过程
2013-12-19 20:11 10764Netty是采用了Reactor模式的多线程版本,建议先看下面 ... -
Netty源码学习-Java-NIO-Reactor
2013-12-19 18:21 4895Netty里面采用了NIO-based Reactor Pat ... -
Netty源码学习-ReplayingDecoder
2013-12-13 20:21 4267ReplayingDecoder是FrameDecoder的子 ... -
Netty源码学习-DefaultChannelPipeline2
2013-12-11 15:47 1285Netty3的API http://docs.jboss.or ... -
Netty源码学习-CompositeChannelBuffer
2013-12-06 15:54 2763CompositeChannelBuffer体现了Netty的 ... -
Netty源码学习-ObjectEncoder和ObjectDecoder
2013-12-05 16:06 5008Netty中传递对象的思路很直观: Netty中数据的传递是基 ... -
Netty源码学习-LengthFieldBasedFrameDecoder
2013-12-05 15:20 7310先看看LengthFieldBasedFrameDecoder ... -
Netty源码学习-FrameDecoder
2013-11-28 18:38 3939Netty 3.x的user guide里FrameDecod ... -
Netty源码学习-DefaultChannelPipeline
2013-11-27 17:00 2243package com.ljn.channel; /** ...
相关推荐
netty-buffer-4.1.32.Final-sources.jar netty-buffer-4.1.32.Final.jar netty-build-22-sources.jar netty-build-22.jar netty-codec-4.1.32.Final-sources.jar netty-codec-4.1.32.Final.jar netty-codec-...
赠送jar包:netty-codec-mqtt-4.1.73.Final.jar; 赠送原API文档:netty-codec-mqtt-4.1.73.Final-javadoc.jar; 赠送源代码:netty-codec-mqtt-4.1.73.Final-sources.jar; 赠送Maven依赖信息文件:netty-codec-...
赠送jar包:netty-transport-native-unix-common-4.1.73.Final.jar; 赠送原API文档:netty-transport-native-unix-common-4.1.73.Final-javadoc.jar; 赠送源代码:netty-transport-native-unix-common-4.1.73....
赠送jar包:netty-resolver-dns-4.1.65.Final.jar; 赠送原API文档:netty-resolver-dns-4.1.65.Final-javadoc.jar; 赠送源代码:netty-resolver-dns-4.1.65.Final-sources.jar; 赠送Maven依赖信息文件:netty-...
赠送jar包:netty-transport-classes-epoll-4.1.73.Final.jar; 赠送原API文档:netty-transport-classes-epoll-4.1.73.Final-javadoc.jar; 赠送源代码:netty-transport-classes-epoll-4.1.73.Final-sources.jar;...
赠送jar包:netty-codec-http2-4.1.74.Final.jar; 赠送原API文档:netty-codec-http2-4.1.74.Final-javadoc.jar; 赠送源代码:netty-codec-http2-4.1.74.Final-sources.jar; 赠送Maven依赖信息文件:netty-codec-...
赠送jar包:netty-codec-dns-4.1.65.Final.jar; 赠送原API文档:netty-codec-dns-4.1.65.Final-javadoc.jar; 赠送源代码:netty-codec-dns-4.1.65.Final-sources.jar; 赠送Maven依赖信息文件:netty-codec-dns-...
赠送jar包:netty-codec-haproxy-4.1.73.Final.jar; 赠送原API文档:netty-codec-haproxy-4.1.73.Final-javadoc.jar; 赠送源代码:netty-codec-haproxy-4.1.73.Final-sources.jar; 赠送Maven依赖信息文件:netty-...
赠送jar包:netty-transport-classes-epoll-4.1.74.Final.jar; 赠送原API文档:netty-transport-classes-epoll-4.1.74.Final-javadoc.jar; 赠送源代码:netty-transport-classes-epoll-4.1.74.Final-sources.jar;...
赠送jar包:netty-transport-rxtx-4.1.74.Final.jar; 赠送原API文档:netty-transport-rxtx-4.1.74.Final-javadoc.jar; 赠送源代码:netty-transport-rxtx-4.1.74.Final-sources.jar; 赠送Maven依赖信息文件:...
赠送jar包:netty-resolver-dns-4.1.65.Final.jar; 赠送原API文档:netty-resolver-dns-4.1.65.Final-javadoc.jar; 赠送源代码:netty-resolver-dns-4.1.65.Final-sources.jar; 赠送Maven依赖信息文件:netty-...
赠送jar包:netty-codec-http2-4.1.73.Final.jar; 赠送原API文档:netty-codec-http2-4.1.73.Final-javadoc.jar; 赠送源代码:netty-codec-http2-4.1.73.Final-sources.jar; 赠送Maven依赖信息文件:netty-codec-...
赠送jar包:netty-transport-classes-epoll-4.1.73.Final.jar; 赠送原API文档:netty-transport-classes-epoll-4.1.73.Final-javadoc.jar; 赠送源代码:netty-transport-classes-epoll-4.1.73.Final-sources.jar;...
赠送jar包:netty-transport-native-unix-common-4.1.74.Final.jar; 赠送原API文档:netty-transport-native-unix-common-4.1.74.Final-javadoc.jar; 赠送源代码:netty-transport-native-unix-common-4.1.74....
赠送jar包:netty-codec-redis-4.1.73.Final.jar; 赠送原API文档:netty-codec-redis-4.1.73.Final-javadoc.jar; 赠送源代码:netty-codec-redis-4.1.73.Final-sources.jar; 赠送Maven依赖信息文件:netty-codec-...
赠送jar包:netty-codec-http-4.1.27.Final.jar; 赠送原API文档:netty-codec-http-4.1.27.Final-javadoc.jar; 赠送源代码:netty-codec-http-4.1.27.Final-sources.jar; 赠送Maven依赖信息文件:netty-codec-...
赠送jar包:netty-resolver-dns-4.1.73.Final.jar; 赠送原API文档:netty-resolver-dns-4.1.73.Final-javadoc.jar; 赠送源代码:netty-resolver-dns-4.1.73.Final-sources.jar; 赠送Maven依赖信息文件:netty-...
赠送jar包:netty-transport-native-unix-common-4.1.68.Final.jar; 赠送原API文档:netty-transport-native-unix-common-4.1.68.Final-javadoc.jar; 赠送源代码:netty-transport-native-unix-common-4.1.68....
赠送jar包:netty-codec-mqtt-4.1.74.Final.jar; 赠送原API文档:netty-codec-mqtt-4.1.74.Final-javadoc.jar; 赠送源代码:netty-codec-mqtt-4.1.74.Final-sources.jar; 赠送Maven依赖信息文件:netty-codec-...
赠送jar包:netty-codec-http-4.1.68.Final.jar; 赠送原API文档:netty-codec-http-4.1.68.Final-javadoc.jar; 赠送源代码:netty-codec-http-4.1.68.Final-sources.jar; 赠送Maven依赖信息文件:netty-codec-...