netty-netty使用jboss marshalling编解码器

netty-netty使用jboss marshalling编解码器

摘自<netty权威指南>

Jboss Marshalling是一个java对象序列化包,对jdk默认的序列化框架进行了优化,又保持了java.io.Serializable接口的兼容书书性

引入依赖

<dependency>
    <groupId>org.jboss.marshalling</groupId>
    <artifactId>jboss-marshalling-serial</artifactId>
    <version>2.0.0.Beta2</version>
</dependency>

服务器端

解码器工厂类MarshallingCodeCFactory:

public class MarshallingCodeCFactory {

	public static MarshallingDecoder buildMarshallingDecoder(){
		MarshallerFactory factory = Marshalling.getProvidedMarshallerFactory("serial");
		MarshallingConfiguration configuration = new MarshallingConfiguration();
		configuration.setVersion(5);
		UnmarshallerProvider provider
                 = new DefaultUnmarshallerProvider(factory, configuration);
		return new MarshallingDecoder(provider, 1024);
	}

	public static MarshallingEncoder buildMarshallingEncoder(){
		MarshallerFactory factory = Marshalling.getProvidedMarshallerFactory("serial");
		MarshallingConfiguration configuration = new MarshallingConfiguration();
		configuration.setVersion(5);
		MarshallerProvider provider 
                        = new DefaultMarshallerProvider(factory, configuration);
		return new MarshallingEncoder(provider);
	}

}

public class EchoServer {

private int port;

public EchoServer(int port) {
	this.port = port;
}


public static void main(String[] args) throws InterruptedException {

	int port = 8080;
	new EchoServer(port).start();
}

private void start() throws InterruptedException {

	EventLoopGroup boss = new NioEventLoopGroup();
	EventLoopGroup work = new NioEventLoopGroup();
	try {
		ServerBootstrap b = new ServerBootstrap();
		b.group(boss, work)
        .channel(NioServerSocketChannel.class)
        .option(ChannelOption.SO_BACKLOG, 100)
        .childHandler(new ChannelInitializer<SocketChannel>() {
            @Override
            protected void initChannel(SocketChannel ch) throws Exception {

                ch.pipeline().addLast(MarshallingCodeCFactory.buildMarshallingDecoder());
                ch.pipeline().addLast(MarshallingCodeCFactory.buildMarshallingEncoder());
                ch.pipeline().addLast(new SubReqServerHandler());

            }
        });
		ChannelFuture future = b.bind(port);
		future.addListener(new ChannelFutureListener() {
			@Override
			public void operationComplete(ChannelFuture future) throws Exception {
				if (future.isSuccess()){
					System.out.println("server start success...");
				}else {
					System.out.println("server start failed...");
				}
			}
		});
		future.channel().closeFuture().sync();
	} finally {

		boss.shutdownGracefully();
		work.shutdownGracefully();
	}

}

}

SubReqServerHandler:

public class SubReqServerHandler extends ChannelInboundHandlerAdapter {


	@Override
	public void channelRead(ChannelHandlerContext ctx,
                                     Object msg) throws Exception {
		SubscribeReq req = (SubscribeReq) msg;
		if ("netty".equalsIgnoreCase(req.getUserName())) {
			System.out.println("server recv req[x] : [" + req.toString() + "]");
			ctx.writeAndFlush(resp(req.getSubReqID()));
		}
	}

	private SubscribeResp resp(int subReqID) {
		SubscribeResp resp = new SubscribeResp();
		resp.setSubReqID(subReqID);
		resp.setDesc("netty book subscribe success...");
		resp.setRespCode(0);
		return resp;
	}


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

客户端

public class EchoClient {


	private String host;
	private int port;

	public EchoClient(String host, int port) {
		this.host = host;
		this.port = port;
	}

	public static void main(String[] args) throws Exception {
		int port = 8080;
		String host = "127.0.0.1";
		new EchoClient(host, port).connect();
	}

	private void connect() throws Exception {

		EventLoopGroup boss = new NioEventLoopGroup();
		try {
			Bootstrap b = new Bootstrap();
			b.group(boss)
            .channel(NioSocketChannel.class)
            .option(ChannelOption.TCP_NODELAY, true)
            .handler(new ChannelInitializer<SocketChannel>() {
                @Override
                protected void initChannel(SocketChannel ch) throws Exception {

                    ch.pipeline().addLast(MarshallingCodeCFactory.buildMarshallingDecoder());
                    ch.pipeline().addLast(MarshallingCodeCFactory.buildMarshallingEncoder());
                    ch.pipeline().addLast(new SubReqClientHandler());


                }
            });
			ChannelFuture future = b.connect(host, port).sync();
			future.channel().closeFuture().sync();
		} finally {
			boss.shutdownGracefully();
		}
	}
}

SubReqClientHandler:

public class SubReqClientHandler extends ChannelInboundHandlerAdapter {


	@Override
	public void channelRead(ChannelHandlerContext ctx, 
                                        Object msg) throws Exception {
		System.out.println("client recv [x]: [" + msg + "]");
	}

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


	@Override
	public void channelActive(ChannelHandlerContext ctx) throws Exception {
		for (int i = 0; i < 10; i++) {
			ctx.write(subReq(i));
		}
		ctx.flush();
	}

	private SubscribeReq subReq(int i) {
		SubscribeReq req = new SubscribeReq();
		req.setSubReqID(i);
		req.setProductName("netty definitive book");
		req.setUserName("netty");
		req.setAddress("ShangHai");
		return req;
	}

	@Override
	public void channelReadComplete(ChannelHandlerContext ctx) 
                                                    throws Exception {
		ctx.flush();
	}
}

运行结果:

server start success...
server recv req[x] : [SubscribeReq{subReqID=0, userName='netty', productName='netty definitive book', address='ShangHai'}]
server recv req[x] : [SubscribeReq{subReqID=1, userName='netty', productName='netty definitive book', address='ShangHai'}]
server recv req[x] : [SubscribeReq{subReqID=2, userName='netty', productName='netty definitive book', address='ShangHai'}]

# client
client recv [x]: [SubscribeResp{subReqID=0, respCode=0, desc='netty book subscribe success...'}]
client recv [x]: [SubscribeResp{subReqID=1, respCode=0, desc='netty book subscribe success...'}]
client recv [x]: [SubscribeResp{subReqID=2, respCode=0, desc='netty book subscribe success...'}]

注意事项

可以发现并没有发生半包的问题,原因是MarshallingDecoder继承了LengthFieldBasedFrameDecoder,而LengthFieldBasedFrameDecoder是用来解决半包问题的:

public class MarshallingDecoder extends LengthFieldBasedFrameDecoder {
    ...
}
发布了76 篇原创文章 · 获赞 66 · 访问量 51万+

猜你喜欢

转载自blog.csdn.net/u013887008/article/details/104182310