Jelajahi Sumber

netty intheader codec

zhzhenqin 12 tahun lalu
induk
melakukan
46d1be2192

+ 68 - 0
netty-intheader-codec/IntegerHeaderFrameDecoder.java

@@ -0,0 +1,68 @@
+package net.dnio.codec.intheader;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.jboss.netty.channel.Channel;
+import org.jboss.netty.channel.ChannelHandlerContext;
+import org.jboss.netty.handler.codec.frame.FrameDecoder;
+
+/**
+ *
+ * <p>
+ *     因为Netty是异步发送和接收消息, 接收端每次只能接收1024字节的数据。
+ *     因此超过1024字节的消息会被分割。利用次消息头则可以获得的完整的消息
+ * </p>
+ *
+ * <pre>
+ *
+ * Created by IntelliJ IDEA.
+ * User: zhenqin
+ * Date: 13-6-4
+ * Time: 下午8:10
+ * To change this template use File | Settings | File Templates.
+ *
+ * </pre>
+ *
+ * @author zhenqin
+ */
+public class IntegerHeaderFrameDecoder extends FrameDecoder {
+
+
+    public IntegerHeaderFrameDecoder() {
+    }
+
+    public IntegerHeaderFrameDecoder(boolean unfold) {
+        super(unfold);
+    }
+
+    @Override
+    public Object decode(ChannelHandlerContext ctx,
+                            Channel channel,
+                            ChannelBuffer buf) throws Exception {
+
+        // Make sure if the length field was received.
+        if (buf.readableBytes() < 4) {
+            // 消息长度小于4字节,则是不正确的消息
+            return null;
+        }
+
+        // 给当前Reader 的Buffer做标记
+        buf.markReaderIndex();
+
+        // 取得消息头,得到该消息的真实长度
+        int length = buf.readInt();
+
+        // 如果此次buffer读取的消息长度小于消息头的长度,则说明消息没有完成
+        if (buf.readableBytes() < length) {
+            // 重置消息的Reader的位置
+            buf.resetReaderIndex();
+            return null;
+        }
+
+        // There's enough bytes in the buffer. Read it.
+        //直到所有的消息都存在于Buffered时, 开始读取
+        ChannelBuffer frame = buf.readBytes(length);
+
+        // Successfully decoded a frame.  Return the decoded frame.
+        return frame;
+    }
+}

+ 71 - 0
netty-intheader-codec/IntegerHeaderFrameEncoder.java

@@ -0,0 +1,71 @@
+package net.dnio.codec.intheader;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.jboss.netty.buffer.ChannelBuffers;
+import org.jboss.netty.channel.Channel;
+import org.jboss.netty.channel.ChannelHandlerContext;
+import org.jboss.netty.handler.codec.oneone.OneToOneEncoder;
+
+/**
+ *
+ * <p>
+ *     该类会在消息头部写上一个标识消息长度的int的值。
+ *     用于在接收端识别消息的总长度,从而得到一个完整的消息体。
+ * </p>
+ *
+ *
+ * <p>
+ *     因为Netty是异步发送和接收消息, 接收端每次只能接收1024字节的数据。
+ *     因此超过1024字节的消息会被分割。利用次消息头则可以获得的完整的消息
+ * </p>
+ *
+ * <pre>
+ *
+ * Created by IntelliJ IDEA.
+ * User: zhenqin
+ * Date: 13-6-4
+ * Time: 下午8:10
+ * To change this template use File | Settings | File Templates.
+ *
+ * </pre>
+ *
+ * @author zhenqin
+ */
+public class IntegerHeaderFrameEncoder  extends OneToOneEncoder {
+
+
+
+    /**
+     * 日志记录
+     */
+    private static Log log = LogFactory.getLog(IntegerHeaderFrameEncoder.class);
+
+
+    public IntegerHeaderFrameEncoder() {
+
+    }
+
+    @Override
+    public Object encode(ChannelHandlerContext ctx, Channel channel, Object msg) throws Exception {
+        if (!(msg instanceof ChannelBuffer)) {
+            return msg;
+        }
+
+        //取得消息正文
+        ChannelBuffer body = (ChannelBuffer) msg;
+
+        //构造一个和原消息等长的消息, 并且加上一个int所占用的内存
+        ChannelBuffer buffer = ChannelBuffers.buffer(body.capacity() + 4);
+
+        //写入消息长度
+        buffer.writeInt(body.writerIndex());
+
+        //写入消息
+        buffer.writeBytes(body);
+
+        //返回一个构造的完整的消息
+        return buffer;
+    }
+}