文档章节

Netty实现自定义简单的编解码器(一)

秋风醉了
 秋风醉了
发布于 2014/06/22 23:00
字数 880
阅读 8683
收藏 7

关于编解码器的介绍,请看我另一篇文章:http://my.oschina.net/xinxingegeya/blog/282878

在这里实现的编解码器很简单,实现int->bytes的编码和bytes->int的解码

具体细节请看代码,注释很全面,运行结果很能说明问题


编码器

package codec.encoder;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToByteEncoder;

public class IntegerToByteEncoder extends MessageToByteEncoder<Integer> {
    @Override
    public void encode(ChannelHandlerContext ctx, Integer msg, ByteBuf out)
            throws Exception {
        System.err.println("IntegerToByteEncoder encode msg is " + msg);
        out.writeInt(msg);
    }
}


解码器

package codec.decoder;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;

import java.util.List;

/**
 * 把字节转换为int
 * 继承抽象类ByteToMessageDecoder实现解码器
 */
public class ByteToIntegerDecoder extends ByteToMessageDecoder {

    @Override
    public void decode(ChannelHandlerContext ctx, ByteBuf in,
                       List<Object> out) throws Exception {
        if (in.readableBytes() >= 4) {  // Check if there are at least 4 bytes readable
            int n = in.readInt();
            System.err.println("ByteToIntegerDecoder decode msg is " + n);
            out.add(n);      //Read integer from inbound ByteBuf, add to the List of decodec messages
        }
    }
}


服务器端程序

package codec;

import codec.decoder.ByteToIntegerDecoder;
import codec.encoder.IntegerToByteEncoder;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;

/**
 * 主要思路:
 * 实现了一个编码器IntegerToByteEncoder和一个解码器ByteToIntegerDecoder
 * 客户端直接发送一个数字
 * 服务器端接收后向客户端发送一个数字
 * 在这过程中可以看到解码器和编码器所起的作用
 */
public class HelloServer {
    public void start(int port) throws Exception {
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        try {
            ServerBootstrap b = new ServerBootstrap();
            b.group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)
                    .option(ChannelOption.SO_BACKLOG, 128)
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        public void initChannel(SocketChannel ch) throws Exception {
                            // 注册handler
                            ch.pipeline().addLast(
                                    new IntegerToByteEncoder(),
                                    new ByteToIntegerDecoder(),
                                    new HelloServerInHandler());
                        }
                    });

            ChannelFuture f = b.bind(port).sync();
            f.channel().closeFuture().sync();

        } finally {
            workerGroup.shutdownGracefully();
            bossGroup.shutdownGracefully();
        }
    }

    public static void main(String[] args) throws Exception {
        HelloServer server = new HelloServer();
        server.start(12345);
    }
}
package codec;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;

// 该handler是InboundHandler类型
public class HelloServerInHandler extends ChannelInboundHandlerAdapter {
    @Override
    public boolean isSharable() {
        System.out.println("==============handler-sharable==============");
        return super.isSharable();
    }

    @Override
    public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
        System.out.println("==============channel-register==============");
    }

    @Override
    public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
        System.out.println("==============channel-unregister==============");
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        System.out.println("==============channel-active==============");

    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        System.out.println("==============channel-inactive==============");
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {

        System.out.println("==============channel-read==============");
        System.out.println("the msg type is " + msg.getClass().getName());
        Integer integer = (Integer) msg;
        System.out.println("服务器端接收到的客户端的数字是" + integer);


        System.out.println("服务器向客户端写入整型数字2000");
        ctx.writeAndFlush(2000);
        ctx.close();
    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        System.out.println("==============channel-read-complete==============");
        ctx.flush();
    }
}


客户端程序

package codec;


import codec.decoder.ByteToIntegerDecoder;
import codec.encoder.IntegerToByteEncoder;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;

public class HelloClient {

    public void connect(String host, int port) throws Exception {

        EventLoopGroup workerGroup = new NioEventLoopGroup();

        try {
            Bootstrap b = new Bootstrap();
            b.group(workerGroup);
            b.channel(NioSocketChannel.class);
            b.option(ChannelOption.AUTO_READ, true);
            b.handler(new ChannelInitializer<SocketChannel>() {
                @Override
                public void initChannel(SocketChannel ch) throws Exception {
                    ch.pipeline().addLast(
                            new IntegerToByteEncoder(),
                            new ByteToIntegerDecoder(),
                            new HelloClientIntHandler());
                }
            });
            ChannelFuture f = b.connect(host, port).sync();
            f.channel().closeFuture().sync();
        } finally {
            workerGroup.shutdownGracefully();
        }
    }

    public static void main(String[] args) throws Exception {
        HelloClient client = new HelloClient();
        client.connect("192.168.0.102", 12345);
    }
}
package codec;

import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;


//InboundHandler类型
public class HelloClientIntHandler extends ChannelInboundHandlerAdapter {

    @Override
    public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
        System.out.println("==============channel--register==============");
    }

    @Override
    public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
        System.out.println("==============channel--unregistered==============");
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        System.out.println("==============channel--inactive==============");
    }

    // 连接成功后,向server发送消息
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        System.out.println("==============channel--active==============");
        System.out.println("向服务器端写入1991数字");
        ctx.write(1991);
        ctx.flush();
    }

    // 接收server端的消息,并打印出来
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        System.out.println("==============channel--read==============");
        System.out.println("the msg type is " + msg.getClass().getName());

        Integer result = (Integer) msg;
        System.out.println("接收到服务器数据整形是" + result);
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        cause.printStackTrace();
        ctx.close();
    }
}


运行结果:

服务器端

==============handler-sharable==============

==============channel-register==============

==============channel-active==============

==============channel-read==============

the msg type is java.lang.Integer

服务器端接收到的客户端的数字是1991

服务器向客户端写入整型数字2000

ByteToIntegerDecoder decode msg is 1991

IntegerToByteEncoder encode msg is 2000

==============channel-read-complete==============

==============channel-inactive==============

==============channel-unregister==============

客户端

==============channel--register==============

==============channel--active==============

向服务器端写入1991数字

IntegerToByteEncoder encode msg is 1991

ByteToIntegerDecoder decode msg is 2000

==============channel--read==============

the msg type is java.lang.Integer

接收到服务器数据整形是2000

==============channel--inactive==============

==============channel--unregistered==============


Process finished with exit code 0

=======END=======

© 著作权归作者所有

共有 人打赏支持
秋风醉了
粉丝 236
博文 578
码字总数 419420
作品 0
朝阳
程序员
《Netty In Action》第七章 编解码器Codec

本章介绍 Codec,编解码器 Decoder,解码器 Encoder,编码器 Netty提供了编解码器框架,使得编写自定义的编解码器很容易,并且也很容易重用和封装。本章讨论Netty的编解码器框架以及使用。 ...

残刃O
02/05
5
0
第七章:编解码器Codec

本章介绍 Codec,编解码器 Decoder,解码器 Encoder,编码器 7.1 编解码器Codec 编写一个网络应用程序需要实现某种编解码器,编解码器的作用就是讲原始字节数据与自定义的消息对象进行互转。...

李矮矮
2016/09/26
28
0
Netty 系列六(编解码器).

一、概念 网络传输的单位是字节,如何将应用程序的数据转换为字节,以及将字节转换为应用程序的数据,就要说到到我们该篇介绍的编码器和解码器。 将应用程序的数据转换为网络格式,以及将网络...

JMCui
08/14
0
0
Netty实现自定义简单的编解码器(二)

Netty实现自定义简单的编解码器(二) 关于编解码器请参见:http://my.oschina.net/xinxingegeya/blog/282878 主要思路: 实现了一个IntegerEncoder编码器和一个IntegerDecoder解码器 服务器...

秋风醉了
2014/06/23
0
0
Netty in Action ——— The codec framework

本文是Netty文集中“Netty in action”系列的文章。主要是对Norman Maurer and Marvin Allen Wolfthal 的 《Netty in action》一书简要翻译,同时对重要点加上一些自己补充和扩展。 本章含盖...

tomas家的小拨浪鼓
2017/12/15
0
0

没有更多内容

加载失败,请刷新页面

加载更多

关于网站恶意注册会员

网站发生恶意注册会员,有图形验证码 ,和短信验证码 但是还是有大量恶意注册: session 和 cookie都是可以随便伪造的。 验证码有打码平台。 短信验证有短信验证平台。 IP限制有虚拟拨号/VP...

妖尾巴
25分钟前
0
0
awk命令用法介绍

10月18日任务 9.6/9.7 awk 9.6/9.7 awk命令 head -n2 test.txt|awk -F ':' '{print $1}' head -n2 test.txt|awk -F ':' '{print $0}' awk -F ':' '{print $1"#"$2"#"$3"#"$4}' awk '/oo/ tes......

zgxlinux
26分钟前
0
0
循环

我今天学会了用for循环找出一个数组中的最大值,代码: var rets = [2,4,5,6,7,9,10,15];function arrayMax(arrs) {var max = arrs[0];for(var i = 1,ilen = arrs.length; i < ilen...

墨冥
31分钟前
0
0
10《Java核心技术》之如何保证集合是线程安全的? ConcurrentHashMap如何实现高效地线程安全?

一、提出问题 之前我们一起讨论过两讲 Java 集合框架的典型容器类,它们绝大部分都不是线程安全的,仅有的线程安全实现,比如 Vector、Stack,在性能方面也远不尽如人意。幸好 Java 语言提供...

飞鱼说编程
35分钟前
1
0
SpringBoot 整合 kafka 实现组订阅模式

SpringBoot 整合 kafka 实现组订阅模式: 工程结构图 消息生产者pom.xml配置 <?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xml......

泉天下
40分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部