结合Netty与Protobuf小栗子

原创 2015年11月18日 16:30:48

结合Netty与Protobuf

基于上一篇生成protobuf的例子,接下来看看怎么与netty结合做个demo~

如何基于protobuf生成Java类请参考上一篇:
http://blog.csdn.net/drizzt0878/article/details/49890121

1. 编写服务端响应的protobuf文件

package com.nettydemo.protobuf;
option java_package = "com.nettydemo.protobuf";
option java_outer_classname = "MsgSendResponseProto";

message MsgSendResponse {
  required string msgID = 1;
  required string result = 2;
}

2. 编译并生成MsgSendResponseProto.java


3. 实现的需求

客户端 –> sendMsg –> 服务端
服务端(接收消息后) –> sendMsgResponse –> 客户端(接收响应消息)


4. 代码实现

服务端代码实现:(MsgSendResponseProto.java , MsgSendServer.java , MsgSendServerHandler.java)

public class MsgSendServer {

    private static final Logger logger = Logger.getLogger(MsgSendServer.class);

    public static void main(String[] args) throws Exception {
        ServerBootstrap bootstrap = new ServerBootstrap(new NioServerSocketChannelFactory(
                Executors.newCachedThreadPool(), Executors.newCachedThreadPool()));

        bootstrap.setPipelineFactory(new ChannelPipelineFactory() {

            @Override
            public ChannelPipeline getPipeline() throws Exception {
                ChannelPipeline pipeline = Channels.pipeline();
                // 解码用
                pipeline.addLast("frameDecoder", new LengthFieldBasedFrameDecoder(1024, 0, 4, 0, 4));
                // 构造函数传递要解码成的类型
                pipeline.addLast("protobufDecoder",
                        new ProtobufDecoder(MsgSendProto.MsgSend.getDefaultInstance()));

                // 编码用
                pipeline.addLast("frameEncoder", new LengthFieldPrepender(4));
                pipeline.addLast("protobufEncoder", new ProtobufEncoder());

                // 业务逻辑处理
                pipeline.addLast("handler", new MsgSendServerHandler());
                return pipeline;
            }

        });

        bootstrap.setOption("child.tcpNoDelay", true);
        bootstrap.setOption("child.keepAlive", true);
        bootstrap.bind(new InetSocketAddress(8080));

        logger.info("server start up...");
    }
}

public class MsgSendServerHandler extends SimpleChannelHandler {

    private static final Logger logger = Logger.getLogger(MsgSendServerHandler.class);

    @Override
    public void handleUpstream(ChannelHandlerContext ctx, ChannelEvent e) throws Exception {
        if (e instanceof ChannelStateEvent) {
            logger.info(e.toString());
        }
        super.handleUpstream(ctx, e);
    }

    @Override
    public void messageReceived(ChannelHandlerContext ctx, final MessageEvent e) {
        // 收到客户端发送的消息,已经解码成了MsgSendProto类型
        final MsgSendProto.MsgSend msgSendProto = (MsgSendProto.MsgSend) e.getMessage();
        System.out.println("receive msg from client: " + msgSendProto);

        // 返回成功接收信息给客户端
        MsgSendResponseProto.MsgSendResponse.Builder builder = MsgSendResponseProto.MsgSendResponse.newBuilder();
        builder.setMsgID(msgSendProto.getMsgID());
        builder.setResult("1");
        e.getChannel().write(builder.build());
    }
}

客户端代码实现:( MsgSendProto.java , MsgSendClient.java , MsgSendClientHandler.java )

public class MsgSendClient {

    public static void main(String[] args) {

        ClientBootstrap bootstrap = new ClientBootstrap(new NioClientSocketChannelFactory(
                Executors.newCachedThreadPool(), Executors.newCachedThreadPool()));

        bootstrap.setPipelineFactory(new ChannelPipelineFactory() {

            @Override
            public ChannelPipeline getPipeline() throws Exception {
                ChannelPipeline pipeline = Channels.pipeline();

                // 解码用
                pipeline.addLast("frameDecoder", new LengthFieldBasedFrameDecoder(1024, 0, 4, 0, 4));
                // 构造函数传递要解码成的类型
                pipeline.addLast("protobufDecoder", new ProtobufDecoder(
                        MsgSendResponseProto.MsgSendResponse.getDefaultInstance()));

                // 编码用
                pipeline.addLast("frameEncoder", new LengthFieldPrepender(4));
                pipeline.addLast("protobufEncoder", new ProtobufEncoder());

                // 业务逻辑用
                pipeline.addLast("handler", new MsgSendClientHandler());
                return pipeline;
            }

        });

        ChannelFuture connectFuture = bootstrap.connect(new InetSocketAddress("127.0.0.1", 8080));
        // Wait until the connection is made successfully.
        Channel channel = connectFuture.awaitUninterruptibly().getChannel();
        MsgSendClientHandler handler = channel.getPipeline().get(MsgSendClientHandler.class);

        // send msg
        handler.sendMsg2Server();
    }
}

public class MsgSendClientHandler extends SimpleChannelUpstreamHandler {

    private volatile Channel channel;

    private static final Logger logger = Logger.getLogger(MsgSendClientHandler.class);

    @Override
    public void channelOpen(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
        channel = e.getChannel();
        super.channelOpen(ctx, e);
    }

    @Override
    public void handleUpstream(ChannelHandlerContext ctx, ChannelEvent e) throws Exception {
        if (e instanceof ChannelStateEvent) {
            logger.info(e.toString());
        }
        super.handleUpstream(ctx, e);
    }

    @Override
    public void messageReceived(ChannelHandlerContext ctx, final MessageEvent e) {
        // 收到服务端返回的消息,已经解码成了MsgSendResponse类型
        final MsgSendResponseProto.MsgSendResponse response = (MsgSendResponseProto.MsgSendResponse) e
                .getMessage();
        System.out.println("receive response from server: msgID=" + response.getMsgID() + ", resultCode="
                + response.getResult());
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
        logger.warn("Unexpected exception from downstream.", e.getCause());
        e.getChannel().close();
    }

    public void sendMsg2Server() {
        // 先进行序列化
        MsgSendProto.MsgSend.Builder builder = MsgSendProto.MsgSend.newBuilder();
        builder.setMsgID("20151101");
        builder.setPhone("13100000000");
        builder.setDoneTime(System.currentTimeMillis());
        builder.setEnterpriseID(1);
        builder.setEnterpriseName("enterprise");
        builder.setResult(1);
        builder.setChannelID(1);
        builder.setCarrier(1);
        builder.setBusyType(1);
        builder.setSize(5);
        builder.setUnit(1);
        channel.write(builder.build());
    }
}

运行结果

客户端

这里写图片描述


服务端

这里写图片描述

netty4与protocol buffer结合简易教程

netty4与protocol buffer结合简易教程
  • wodeyuer125
  • wodeyuer125
  • 2014年08月25日 10:36
  • 3137

Mina、Netty、Twisted一起学(五):整合protobuf

protobuf是谷歌的Protocol Buffers的简称,用于结构化数据和字节码之间互相转换(序列化、反序列化),一般应用于网络传输,可支持多种编程语言。protobuf如何使用这里不再介绍,本...
  • xiao__gui
  • xiao__gui
  • 2014年08月27日 09:25
  • 5404

【Netty4.X】Unity与Netty使用protoBuf(四)

客户端与服务器端之间传输的数据格式有很多种如Json、XML、thrift、Protobuf等等。protobuf来自谷歌,它的特点是数据小、编解码性能高、支持多种语言,它序列化后的大小是json的1...
  • liulongling
  • liulongling
  • 2016年09月03日 19:50
  • 2246

Netty protobuf使用,自定义Encoder 和DeCoder

Server 监听客户发送的信息,并且打印 Client 发送5s 发送信息。 1.编辑google 的proto文件 Msg.proto syntax = "proto3"; ...
  • yonghutongxingzhencs
  • yonghutongxingzhencs
  • 2017年05月15日 20:58
  • 286

netty与protobuf结合开发小demo

最近学习netty,于是就有了一下例子:(为什么用protobuf可以在我前一篇文章里面找找) 1.写了一个proto文件生成java代码;(到你的项目所在处执行protoc.exe msg.pro...
  • jane_fast
  • jane_fast
  • 2017年09月13日 17:53
  • 100

Netty使用Protobuf进行编解码

一、下载及安装 Protobuf安装包: https://github.com/google/protobuf/releases/download/v2.6.1/protoc-2.6.1-win32....
  • qq_19983129
  • qq_19983129
  • 2016年11月23日 15:06
  • 909

Unity3D & Java 基于 Protobuf 通信实现

Unity3D & Java 基于 Protobuf 通信实现最近研究Unity3D,同时需要给游戏制定一套通信协议。因为本人是后端出生,对C#的 Socket相关通信框架不太熟悉,经过几天的学习,终...
  • zeus_9i
  • zeus_9i
  • 2015年05月28日 17:27
  • 3202

一起学Netty(十)之 Netty使用Google的ProtoBuf

protobuf是由Google开发的一套对数据结构进行序列化的方法,可用做通信协议,数据存储格式,等等。其特点是不限语言、不限平台、扩展性强 Netty也提供了对Protobuf的天然支持,我们...
  • linuu
  • linuu
  • 2016年05月11日 19:44
  • 15577

Netty protobuf的编解码使用

Netty为protobuf提供了两个编码器(ProtobufEncoder,ProtobufVarint32LengthFieldPrepender),两个解码器(ProtobufVarint32F...
  • zero__007
  • zero__007
  • 2017年06月15日 19:18
  • 847

基于netty的项目中使用protobuf,巧妙定义proto完成不同消息的编码和解码处理 .

在基于netty的项目中使用protobuf,需要处理不同的消息,因此需要不同的编码和解码方式(如下)p.addLast("protobufDecoder", new ProtobufDecoder(...
  • a351945755
  • a351945755
  • 2014年02月18日 16:08
  • 5110
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:结合Netty与Protobuf小栗子
举报原因:
原因补充:

(最多只允许输入30个字)