网络编程复习(九):Netty的编解码技术

编解码技术,说白了就是java的序列化,序列化的作用有两个,网络传输和持久化。

随人我们可以使用java提供的序列化方式,netty去传输,但是有很多硬伤,比如java序列化没法跨语言,序列化后码流太大,序列化性能太低等等。

主流的编解码框架有:

Jboss的marshalling包:今天内容

Google的protobuf;

基于protobuf的Kyro;

MessagePack框架(Netty官方支持的框架)等。

marshalling对JDK提供的序列化方式进行了优化,同时又保持了与原生JDK序列化包的兼容性,同时增加了一些可调参数和附加特性。

marshalling的类库:jboss-mashalling-1.3.0和jboss-mashalling-serial-1.3.0。

Jboss的marshalling与Netty结合使用很简单,下面看看小demo:

client:

package cn.lh.netty;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
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 NettyClient {
	public static void main(String[] args) throws InterruptedException {
		EventLoopGroup group = new NioEventLoopGroup();
		Bootstrap bootstrap = new Bootstrap();
		bootstrap.group(group)
				 .channel(NioSocketChannel.class)
				 .handler(new ChannelInitializer<SocketChannel>() {
					@Override
					public void initChannel(SocketChannel ch) throws Exception {
						ch.pipeline().addLast(MyMarshallingFactory.buildMarshallingDecoder());
						ch.pipeline().addLast(MyMarshallingFactory.buildMarshallingEncoder());
						ch.pipeline().addLast(new NettyClientHandler());
					}
				});
		ChannelFuture f = bootstrap.connect("127.0.0.1", 8888).sync();
		for(int i=1;i<=5;i++){
			Request request = new Request();
			request.setId(i);
			request.setMsg("这是请求内容:"+i);
			f.channel().writeAndFlush(request);
		}
		f.channel().closeFuture().sync();
		group.shutdownGracefully();
	}
}

NettyClientHandler类:

package cn.lh.netty;

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

public class NettyClientHandler extends ChannelHandlerAdapter{

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

	@Override
	public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
		try {
			Response res = (Response) msg;
			System.out.println("server response:"+res.getId()+"--"+res.getName());
		}finally {
			ReferenceCountUtil.release(msg);
		}
	}

	
}
MyMarshallingFactory类:

package cn.lh.netty;

import org.jboss.marshalling.MarshallerFactory;
import org.jboss.marshalling.Marshalling;
import org.jboss.marshalling.MarshallingConfiguration;

import io.netty.handler.codec.marshalling.DefaultMarshallerProvider;
import io.netty.handler.codec.marshalling.DefaultUnmarshallerProvider;
import io.netty.handler.codec.marshalling.MarshallerProvider;
import io.netty.handler.codec.marshalling.MarshallingDecoder;
import io.netty.handler.codec.marshalling.MarshallingEncoder;
import io.netty.handler.codec.marshalling.UnmarshallerProvider;

public class MyMarshallingFactory {
	public static MarshallingEncoder buildMarshallingEncoder(){
		MarshallerFactory factory = Marshalling.getProvidedMarshallerFactory("serial");
		MarshallingConfiguration configuration = new MarshallingConfiguration();
		configuration.setVersion(5);
		MarshallerProvider provider = new DefaultMarshallerProvider(factory, configuration);
		MarshallingEncoder encoder = new MarshallingEncoder(provider);
		return encoder;
	}
	public static MarshallingDecoder buildMarshallingDecoder(){
		MarshallerFactory factory = Marshalling.getProvidedMarshallerFactory("serial");
		MarshallingConfiguration configuration = new MarshallingConfiguration();
		configuration.setVersion(5);
		UnmarshallerProvider provider = new DefaultUnmarshallerProvider(factory, configuration);
		MarshallingDecoder decoder = new MarshallingDecoder(provider);
		return decoder;
	}
}
Request类:

package cn.lh.netty;

import java.io.Serializable;

public class Request implements Serializable{

	private static final long serialVersionUID = 2485854233342015229L;

	private int id;
	private String msg;
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getMsg() {
		return msg;
	}
	public void setMsg(String msg) {
		this.msg = msg;
	}
	
	
}

Response类:


package cn.lh.netty;

import java.io.Serializable;

public class Response implements Serializable{
	private static final long serialVersionUID = 3045830684163490285L;

	private int id;
	private String name;
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	
	
}
NettyServer类:

package cn.lh.netty;


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;

public class NettyServer {
	public static void main(String[] args) throws InterruptedException {
		EventLoopGroup boss = new NioEventLoopGroup();
		EventLoopGroup worker = new NioEventLoopGroup();
		ServerBootstrap bootstrap = new ServerBootstrap();
		bootstrap.group(boss, worker)
				 .option(ChannelOption.SO_BACKLOG, 1024)
				 .option(ChannelOption.SO_KEEPALIVE, true)
				 .option(ChannelOption.SO_SNDBUF, 32*1024)
				 .option(ChannelOption.SO_RCVBUF, 32*1024)
				 .channel(NioServerSocketChannel.class)
				 .childHandler(new ChannelInitializer<SocketChannel>() {
					@Override
					public void initChannel(SocketChannel ch) throws Exception {
						ch.pipeline().addLast(MyMarshallingFactory.buildMarshallingDecoder());
						ch.pipeline().addLast(MyMarshallingFactory.buildMarshallingEncoder());
						ch.pipeline().addLast(new NettyServerHandler());
					}
				});
		ChannelFuture f = bootstrap.bind(8888).sync();
		f.channel().closeFuture().sync();
		boss.shutdownGracefully();
		worker.shutdownGracefully();
				 
	}
}

NettyServerHandler类:


package cn.lh.netty;

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

public class NettyServerHandler extends ChannelHandlerAdapter{

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

	@Override
	public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
		Request request = (Request) msg;
		System.out.println("client request:"+request.getId()+request.getMsg());
		Response res = new Response();
		res.setId(request.getId());
		res.setName("回应消息"+request.getId());
		ctx.channel().writeAndFlush(res);
	}

	
}

输出结果:

client:

server response:1--回应消息1
server response:2--回应消息2
server response:3--回应消息3
server response:4--回应消息4
server response:5--回应消息5

server:

client request:1这是请求内容:1
client request:2这是请求内容:2
client request:3这是请求内容:3
client request:4这是请求内容:4
client request:5这是请求内容:5


注意:这里我在用maven依赖jar包的时候新版本的marshalling的jar包导入不起作用,不发送消息也不报错,搞了半天,可能最新版本的marshalling编解码技术实现改变了,以后在研究,这里使用1.3.0.CR9的jar包即可使用。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值