文档章节

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

秋风醉了
 秋风醉了
发布于 2014/06/22 23:00
字数 880
阅读 8214
收藏 7
点赞 0
评论 0

关于编解码器的介绍,请看我另一篇文章: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=======

© 著作权归作者所有

共有 人打赏支持
秋风醉了
粉丝 222
博文 581
码字总数 411013
作品 0
东城
程序员
《Netty In Action》第七章 编解码器Codec

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

残刃O ⋅ 02/05 ⋅ 0

第七章:编解码器Codec

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

李矮矮 ⋅ 2016/09/26 ⋅ 0

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

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

秋风醉了 ⋅ 2014/06/23 ⋅ 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

第十四章:实现自定义的编码解码器

14.1 编解码器的范围 我们将只实现Memcached协议的一个子集,这足够我们进行添加、检索、删除对象;在Memcached中是通过执行SET,GET,DELETE命令来实现的。Memcached支持很多其他的命令,但我...

李矮矮 ⋅ 2016/09/27 ⋅ 0

Netty解决TCP的粘包和分包(一)

Netty解决TCP的粘包和分包(一) 关于TCP的粘包和分包:http://my.oschina.net/xinxingegeya/blog/484824 Netty分包 分包的解决办法: 1、消息定长,报文大小固定长度,不够空格补全,发送和...

秋风醉了 ⋅ 2015/07/29 ⋅ 0

Netty读书笔记4: 编码器解码器详解

1. 编码器解码器的引入 通常情况下,当我们得到ByteBuf情况下,我们如果得解码得到我们想要的消息,通常情况下是如下这样处理 这样的一个弊端是,每次InBoundHandler的channelRead读取数据时候,...

maskwang520 ⋅ 04/01 ⋅ 0

第八章:附带的ChannelHandler和Codec

本章介绍 使用SSL/TLS创建安全的Netty程序 使用Netty创建HTTP/HTTPS程序 处理空闲连接和超时 解码分隔符和基于长度的协议 写大数据 序列化数据 上一章讲解了如何创建自己的编解码器,我们现在...

李矮矮 ⋅ 2016/09/26 ⋅ 0

Netty with protobuf(二)

http://my.oschina.net/xinxingegeya/blog/295031 上一篇了解了protobuf,现在结合netty做一个例子。 关键就是配置netty的编解码器,因为netty提供了protobuf的编解码器,所以我们可以很容易...

秋风醉了 ⋅ 2014/07/26 ⋅ 0

dubbo通信消息解析过程分析(1)

由于rpc底层涉及网络编程接口,线程模型,网络数据结构,服务协议,细到字节的处理。牵涉内容较多,今天就先从一个点说起。 说说,dubbo通过netty框架做传输层,从接到数据字节流到把字节转换...

wannshan ⋅ 01/19 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

iExec Blockchain Marketplace for Cloud

iExec Releases the First-Ever Blockchain Marketplace for Trading Cloud Computing Berlin, Germany, May 29, 2018. iExec has released its blockchain-based decentralized cloud marke......

openthings ⋅ 25分钟前 ⋅ 0

OSChina 周二乱弹 —— 加班的代码不要枉费了我的童子功

Osc乱弹歌单(2018)请戳(这里) 【今日歌曲】 @小小编辑:推荐歌曲《29》- 未完成乐队 《29》- 未完成乐队 手机党少年们想听歌,请使劲儿戳(这里) @FalconChen :#看球提醒# 02:00 巴西v...

小小编辑 ⋅ 44分钟前 ⋅ 13

Docker Swarm的前世今生

概述 在我的《Docker Swarm集群初探》一文中,我们实际体验了Docker Swarm容器集群技术的魅力,与《Kubernetes实践录》一文中提到的Kubernetes集群技术相比,Docker Swarm没有Kubernetes显得...

CodeSheep ⋅ 今天 ⋅ 0

骰子游戏代码开源地址

因为阿里云现在服务器已经停用了,所以上面的配置已经失效。 服务端开源地址:https://gitee.com/goalya/chat4.git 客户端开源地址:https://gitee.com/goalya/client4.git 具体运行界面请参考...

算法之名 ⋅ 今天 ⋅ 0

设计模式--装饰者模式

装饰者模式 定义 动态地给一个对象添加一些额外的职责。就增加功能来说,装饰模式相比生成子类更为灵活。 通用类图 意图 动态地给一个对象添加一些额外的职责。就增加功能来说,装饰模式相比...

gaob2001 ⋅ 今天 ⋅ 0

JavaScript零基础入门——(八)JavaScript的数组

JavaScript零基础入门——(八)JavaScript的数组 欢迎大家回到我们的JavaScript零基础入门,上一节课我们讲了有关JavaScript正则表达式的相关知识点,便于大家更好的对字符串进行处理。这一...

JandenMa ⋅ 今天 ⋅ 0

sbt网络问题解决方案

转自:http://dblab.xmu.edu.cn/blog/maven-network-problem/ cd ~/.sbt/launchers/0.13.9unzip -q ./sbt-launch.jar 修改 vi sbt/sbt.boot.properties 增加一个oschina库地址: [reposit......

狐狸老侠 ⋅ 今天 ⋅ 0

大数据,必须掌握的10项顶级安全技术

我们看到越来越多的数据泄漏事故、勒索软件和其他类型的网络攻击,这使得安全成为一个热门话题。 去年,企业IT面临的威胁仍然处于非常高的水平,每天都会看到媒体报道大量数据泄漏事故和攻击...

p柯西 ⋅ 今天 ⋅ 0

Linux下安装配置Hadoop2.7.6

前提 安装jdk 下载 wget http://mirrors.hust.edu.cn/apache/hadoop/common/hadoop-2.7.6/hadoop-2.7.6.tar.gz 解压 配置 vim /etc/profile # 配置java环境变量 export JAVA_HOME=/opt/jdk1......

晨猫 ⋅ 今天 ⋅ 0

crontab工具介绍

crontab crontab 是一个用于设置周期性被执行的任务工具。 周期性执行的任务列表称为Cron Table crontab(选项)(参数) -e:编辑该用户的计时器设置; -l:列出该用户的计时器设置; -r:删除该...

Linux学习笔记 ⋅ 今天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部