1. 程式人生 > >netty 編解碼之 Messagepack

netty 編解碼之 Messagepack

首先說一下需要注意的問題

1:傳送端的javabean 一定要有註解 @Message。這個註解要加在類上。使用@Message 可以標記被序列化的類。類中所有成員都會被序列化。 否則javabean不會被序列化,也就接收不到了。接收端的javabean可以不加這個註解。習慣性的兩個端都會加上。

2、因為有  @Message 所以javabean就不需要實現Serializable介面,當然實現了也沒有問題(已測);

3、傳送的javabean要在Client和Server端兩個端都存在,而且名稱要完全一致,全類名一致。或者直接打成單獨的jar包放在兩個端;

4、傳送端編碼,服務解碼。也就是說,編碼和和解碼的類不一定要兩個端都有。

5、網上有許多關於messagepack拆包的問題,我發現我沒有發生粘包。。。所以,沒有處理這一塊。有需要的朋友網上找找,很多的。

netty權威指南里也有相關的介紹。

遇到的坑:(1)一開始沒有加上@Message註解(2)解碼的一段程式碼應該是msg.getBytes(msg.readerIndex(), array, 0, length);但是寫成 了msg.getBytes(msg.readableBytes(), array, 0, length); 導致解碼出的msg長度0,沒有內容;

其他的問題暫無。

下面看具體程式碼,client端和server端是兩個不同的工程。

javabean 和編碼解碼的程式碼兩個端是一樣的,這裡提供一份。

handler 寫的比較簡單,可以根據需要改改;

Client端的程式碼:

NettyClient.java
package com.aowin.netty.serial.messagepack;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;

public class 
NettyClient { public void connet(){ EventLoopGroup bosLoup=new NioEventLoopGroup(); Bootstrap bootstrap=new Bootstrap(); bootstrap.group(bosLoup) .channel(NioSocketChannel.class) .handler(new NettyClientInitializer()); try { ChannelFuture future= bootstrap.connect("127.0.0.1",8765).sync(); UserInfo userInfoArray[]=new UserInfo[3]; for(int i=0;i<3;i++){ UserInfo userInfo=new UserInfo(); userInfo.setName("netty"); userInfo.setAge(i); userInfoArray[i]=userInfo; } // future.channel().writeAndFlush(Unpooled.copiedBuffer("hello".getBytes())); future.channel().writeAndFlush(userInfoArray); future.channel().closeFuture().sync(); bosLoup.shutdownGracefully(); } catch (InterruptedException e) { e.printStackTrace(); } } public static void main(String[] args) { NettyClient client=new NettyClient(); client.connet(); } }
NettyClientHandler.java  
package com.aowin.netty.serial.messagepack;

import io.netty.channel.ChannelHandlerAdapter;
import io.netty.channel.ChannelHandlerContext;

public class NettyClientHandler  extends ChannelHandlerAdapter{
    @Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
    }

    @Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
    }

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

    @Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
    }
}
NettyClientInitializer.java
package com.aowin.netty.serial.messagepack;

import io.netty.channel.Channel;
import io.netty.channel.ChannelInitializer;
import io.netty.handler.codec.string.StringDecoder;

public class NettyClientInitializer extends ChannelInitializer{
    @Override
protected void initChannel(Channel ch) throws Exception {
        //ch.pipeline().addLast(new StringDecoder());
ch.pipeline().addLast(new MsgPackEncode());
        ch.pipeline().addLast(new MsgPackDecode());
        ch.pipeline().addLast(new NettyClientHandler());

    }
}

Server端的程式碼:

NettyServer.java
package com.aowin.netty.serial.messagepack;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;

public class NettyServer {
    public void bind() {
        EventLoopGroup bosGroup = new NioEventLoopGroup();
        EventLoopGroup workGroup = new NioEventLoopGroup();
        ServerBootstrap bootstrap = new ServerBootstrap();
        bootstrap.group(bosGroup, workGroup)
                .channel(NioServerSocketChannel.class)
                .option(ChannelOption.SO_BACKLOG, 1024)
                .option(ChannelOption.SO_SNDBUF, 32 * 1024)
                .option(ChannelOption.SO_RCVBUF, 32 * 1024)
                .option(ChannelOption.SO_KEEPALIVE, true)
                .handler(new LoggingHandler(LogLevel.DEBUG))
                .childHandler(new NettyServerInitializer());
        try {
            ChannelFuture future = bootstrap.bind("127.0.0.1", 8765).sync();
            future.channel().closeFuture().sync();
            bosGroup.shutdownGracefully();
            workGroup.shutdownGracefully();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        NettyServer server=new NettyServer();
        server.bind();
    }
}
NettyServerHandler.java
package com.aowin.netty.serial.messagepack;

import io.netty.channel.ChannelHandlerAdapter;
import io.netty.channel.ChannelHandlerContext;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.util.List;
import java.util.logging.Logger;

public class NettyServerHandler extends ChannelHandlerAdapter {
    Log logger= LogFactory.getLog(NettyServerHandler.class);
    @Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
    }

    @Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
    }

    @Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        List<UserInfo> list= (List<UserInfo>) msg;

        logger.info(list);
        logger.info(list.get(0));
        logger.info(list.get(1));
    }

    @Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
    }
}
NettyServerInitializer.java
package com.aowin.netty.serial.messagepack;

import io.netty.channel.Channel;
import io.netty.channel.ChannelInitializer;
import io.netty.handler.codec.string.StringDecoder;

public class NettyServerInitializer extends ChannelInitializer {
    protected void initChannel(Channel ch) throws Exception {
        ch.pipeline().addLast(new MsgPackEncode());
        ch.pipeline().addLast(new MsgPackDecode());
        ch.pipeline().addLast(new NettyServerHandler());
    }
}

下面是兩個端都要有的程式碼:

    解碼:

MsgPackDecode.java 
package com.aowin.netty.serial.messagepack;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToMessageDecoder;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.msgpack.MessagePack;

import java.util.List;

public class MsgPackDecode extends MessageToMessageDecoder<ByteBuf> {
private Log logger= LogFactory.getLog(MsgPackDecode.class);
    @Override
protected void decode(ChannelHandlerContext ctx, ByteBuf msg,
                          List<Object> out) throws Exception {
        logger.info("解碼");
        final byte[] array;
        final int length = msg.readableBytes();
        array = new byte[length];
        //msg.getBytes(msg.readableBytes(), array, 0, length);
msg.getBytes(msg.readerIndex(), array, 0, length);
        MessagePack msgPack = new MessagePack();
        out.add(msgPack.read(array));
        logger.info("解碼");
    }

}

編碼:

package com.aowin.netty.serial.messagepack;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToByteEncoder;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.msgpack.MessagePack;

public class MsgPackEncode  extends MessageToByteEncoder<Object> {
    private Log logger= LogFactory.getLog(MsgPackEncode.class);
    @Override
protected void encode(ChannelHandlerContext ctx, Object msg, ByteBuf out)
            throws Exception {
        logger.info("編碼");
        MessagePack msgPack = new MessagePack();
        System.out.println(msg == null);
        byte[] raw = null;
        raw = msgPack.write(msg);
        out.writeBytes(raw);
        logger.info("編碼");
    }
}
javaBean:
package com.aowin.netty.serial.messagepack;

import org.msgpack.annotation.Message;

import java.io.Serializable;

//這個註解是加在類上的
@Messagepublic class UserInfo{
    String name;
    int age;

    public String getName() {
        
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}
執行結果:

客戶端:


服務端:


相關推薦

netty 解碼 Messagepack

首先說一下需要注意的問題1:傳送端的javabean 一定要有註解 @Message。這個註解要加在類上。使用@Message 可以標記被序列化的類。類中所有成員都會被序列化。 否則javabean不會被序列化,也就接收不到了。接收端的javabean可以不加這個註解。習慣性

netty解碼jboss marshalling

netty編解碼之jboss marshalling jboss marshalling是jboss內部的一個序列化框架,速度也十分快,這裡netty也提供了支援,使用十分方便,不需要像protobuf一樣編寫proto檔案,只需要提供兩個編解碼器即可,以下就是jboss ma

netty解碼java原生序列化

netty序列化之java原生序列化 前幾天有空看了下netty使用java原生序列化、以及使用protobuf、jboss marshalling進行編解碼,各種技術之間差異挺大,使用的方法各自不同,效能上原生的效能優勢確實不大,但是另外兩種確實很有優勢,覺得有點意思,於是準

死磕Netty原始碼Netty解碼原始碼解析

前言 Netty的底層是基於TCP實現的,TCP協議在傳輸資料的過程中一個完整的業務可能會被TCP拆分成多個包進行傳送,也有可能把多個小的包封裝成一個大的資料包傳送,因此我們需要考慮Netty的粘包拆包問題 訊息解碼器 Netty提供了拆包的基類Byt

分散式Netty介紹與實戰(四)--Netty解碼程式設計實戰

目錄 分散式之Netty介紹與實戰(一)–Java IO與NIO 分散式之Netty介紹與實戰(二)–Netty程式設計實踐 分散式之Netty介紹與實戰(三)–Netty執行緒模型解析 分散式之Netty介紹與實戰(四)–Netty編解碼程式設計實戰

[netty]-訊息解碼Java原生序列化

訊息物件在網路上傳輸時,我們往往要對訊息進行編解碼。現在編解碼技術非常多,包括Java原生的序列化、Google的protoBuf、hessian等等。這一篇部落格我們主要介紹Java的原生序列化編解碼以及其優缺點。 基於Java提供的物件輸入/輸出流

Netty學習(九)-Netty解碼技術Marshalling

前面我們講過protobuf的使用,主流的編解碼框架其實還有很多種: ①JBoss的Marshalling包 ②google的Protobuf ③基於Protobuf的Kyro ④Apache的Thrift JBoss Marshalling是一個J

Netty系列Netty解碼框架分析

1. 背景 1.1. 編解碼技術 通常我們也習慣將編碼(Encode)稱為序列化(serialization),它將物件序列化為位元組陣列,用於網路傳輸、資料持久化或者其它用途。 反之,解碼(Decode)/反序列化(deserialization)把從網路、磁碟等

Netty(三)——解碼

       我們在開發中經常會把Java類進行implements Serializable用來網路傳輸的序列化和反序列化,過程其實就是將Java物件轉編碼為位元組陣列或者ByteBuffer物件進行傳輸,當遠端服務讀取到ByteBuffer物件或者位元組陣列時,需要將其解

Netty 解碼技術 數據通信和心跳監控案例

base encode lean java語言 附件 rep baidu 類比 syn Netty 編解碼技術 數據通信和心跳監控案例 多臺服務器之間在進行跨進程服務調用時,需要使用特定的編解碼技術,對需要進行網絡傳輸的對象做編碼和解碼操作,以便完成遠程調用。Netty提供

即時通訊音視訊開發(四):視訊解碼預測技術介紹

前言 即時通訊應用中的實時音視訊技術,幾乎是IM開發中的最後一道高牆。原因在於:實時音視訊技術 = 音視訊處理技術 + 網路傳輸技術 的橫向技術應用集合體,而公共網際網路不是為了實時通訊設計的。 系列文章 《即時通訊音視訊開發(二):視訊編解碼之數字視訊介紹》 《即時通訊音

即時通訊音視訊開發(三):視訊解碼編碼基礎

前言 即時通訊應用中的實時音視訊技術,幾乎是IM開發中的最後一道高牆。原因在於:實時音視訊技術 = 音視訊處理技術 + 網路傳輸技術 的橫向技術應用集合體,而公共網際網路不是為了實時通訊設計的。 系列文章 《即時通訊音視訊開發(一):視訊編解碼之理論概述》 《即時通訊音視訊

即時通訊音視訊開發(二):視訊解碼數字視訊介紹

前言 即時通訊應用中的實時音視訊技術,幾乎是IM開發中的最後一道高牆。原因在於:實時音視訊技術 = 音視訊處理技術 + 網路傳輸技術 的橫向技術應用集合體,而公共網際網路不是為了實時通訊設計的。 系列文章 本文是系列文章中的第2篇,本系列文章的大綱如下:   《即時

即時通訊音視訊開發(一):視訊解碼理論概述

前言 即時通訊應用中的實時音視訊技術,幾乎是IM開發中的最後一道高牆。原因在於:實時音視訊技術 = 音視訊處理技術 + 網路傳輸技術 的橫向技術應用集合體,而公共網際網路不是為了實時通訊設計的。 系列文章 《即時通訊音視訊開發(二):視訊編解碼之數字視訊介紹》 《即時通訊音

Netty(解碼器框架)

    每個網路應用程式都必須定義如何解析在兩個節點之間來回傳輸的原始位元組,以及如何將其和目標應用程式的資料格式做相互轉換。這種轉換邏輯由編解碼器處理,編解碼器  由編碼器和解碼器組成,它們每種都可以將位元組流從一種格式轉換為另一種格式。  

網際網路技術22——netty解碼技術與資料通訊

Netty服務部署 常用的部署方式有2中,一種是耦合在Web應用中(以Tomcat為例),使其伴隨Tomcat的啟動而啟動,伴隨Tomcat的關閉而關閉。另外一種則是將Netty獨立打包部署,然後由單獨的程序啟動執行(可以使用shell或其他指令碼進行啟動),然後以資料庫或者其他快取為承接點,實

iOS學習-即時通訊音視訊(一)視訊解碼理論

參考大神:http://www.52im.net/thread-228-1-1.html 實時音視訊技術 = 音視訊處理技術 + 網路傳輸技術 的橫向技術應用集合體。 視訊為何需要壓縮? 1.未經壓縮的數字視訊的資料量巨大 2. 儲存困難,一張DVD只能儲存幾秒鐘的未壓縮數字視訊 3. 傳輸困難 1

Netty】(9)---Netty解碼

ext 就會 思想 eterm 固定 mit request對象 表示 ase Netty編解碼器 在了解Netty編解碼之前,先了解Java的編解碼: 編碼(Encode)稱為序列化, 它將對象序列化為字節數組,用於網絡傳輸、數據持久化或者其它用途。

【ffmpeg】視訊解碼ffmpeg命令列工具的常用命令彙總

H264視訊轉ts視訊流 ffmpeg -i test.h264 -vcodec copy -f mpegts test.ts H264視訊轉mp4 ffmpeg -i test.h264 -vcodec copy -f mp4 test.mp4 ts視訊轉mp4 ffmpeg

基於Protostuff實現的Netty解碼

發送數據 gets log har not check finally chm sch 在設計netty的編解碼器過程中,有許多組件可以選擇,這裏由於咱對Protostuff比較熟悉,所以就用這個組件了。由於數據要在網絡上傳輸,所以在發送方需要將類對象轉換成二進制,接收方接