Netty学习教程之Netty与Marshalling结合发送对象
前言
之前的一篇文章是Netty简单的学习,我们可以传递一个字符串,那么如果我们想要在Netty中传递一个对象该怎么办呢?
那么这个时候我们可以结合Marshalling来传递。
方法如下:
首先需要导入两个Marshalling的依赖包
jboss-marshalling-1.3.0.CR9.jar jboss-marshalling-serial-1.3.0.CR9.jar
注意:我开始学习的时候只导入了第一个jar包,没有导入第二个,结果是不报错,但是客户端和服务端之间传递不了消息。所以两个包一定要都导入才行。
MarshallingCodeCFactory工具类
publicclassMarshallingCodeCFactory{ publicstaticMarshallingDecoderbuildMarshallingDecoder(){ finalMarshallerFactoryfactory=Marshalling.getProvidedMarshallerFactory("serial"); finalMarshallingConfigurationconfiguration=newMarshallingConfiguration(); configuration.setVersion(5); UnmarshallerProviderprovider=newDefaultUnmarshallerProvider(factory,configuration); MarshallingDecoderdecoder=newMarshallingDecoder(provider,1024*1024); returndecoder; } publicstaticMarshallingEncoderbuildMarshallingEncoder(){ finalMarshallerFactoryfactory=Marshalling.getProvidedMarshallerFactory("serial"); finalMarshallingConfigurationconfiguration=newMarshallingConfiguration(); configuration.setVersion(5); MarshallerProviderprovider=newDefaultMarshallerProvider(factory,configuration); MarshallingEncoderencoder=newMarshallingEncoder(provider); returnencoder; } }
server端
publicclassServer{ publicstaticvoidmain(String[]args)throwsInterruptedException{ //1.第一个线程组是用于接收Client端连接的 EventLoopGroupbossGroup=newNioEventLoopGroup(); //2.第二个线程组是用于实际的业务处理的 EventLoopGroupworkerGroup=newNioEventLoopGroup(); ServerBootstrapb=newServerBootstrap(); b.group(bossGroup,workerGroup);//绑定两个线程池 b.channel(NioServerSocketChannel.class);//指定NIO的模式,如果是客户端就是NioSocketChannel b.option(ChannelOption.SO_BACKLOG,1024);//TCP的缓冲区设置 b.option(ChannelOption.SO_SNDBUF,32*1024);//设置发送缓冲的大小 b.option(ChannelOption.SO_RCVBUF,32*1024);//设置接收缓冲区大小 b.option(ChannelOption.SO_KEEPALIVE,true);//保持连续 b.childHandler(newChannelInitializer(){ protectedvoidinitChannel(SocketChannelch)throwsException{ //设置Marshalling的编码和解码 ch.pipeline().addLast(MarshallingCodeCFactory.buildMarshallingDecoder()); ch.pipeline().addLast(MarshallingCodeCFactory.buildMarshallingEncoder()); ch.pipeline().addLast(newServertHandler()); } }); ChannelFuturefuture=b.bind(8765).sync();//绑定端口 future.channel().closeFuture().sync();//等待关闭(程序阻塞在这里等待客户端请求) bossGroup.shutdownGracefully();//关闭线程 workerGroup.shutdownGracefully();//关闭线程 } }
ServerHandler处理类
publicclassServertHandlerextendsChannelHandlerAdapter{ @Override publicvoidexceptionCaught(ChannelHandlerContextctx,Throwablecause) throwsException{ cause.printStackTrace(); } @Override publicvoidchannelRead(ChannelHandlerContextctx,Objectmsg) throwsException{ Sendsend=(Send)msg; System.out.println("client发送:"+send); Receivereceive=newReceive(); receive.setId(send.getId()); receive.setMessage(send.getMessage()); receive.setName(send.getName()); ctx.writeAndFlush(receive); } }
由于我们已经在Server端和Client端定义了传递的类型又Marshalling工厂处理,所以此时我们接收的时候直接转成发送的对象类型就行了。
Client端
publicclassClient{ publicstaticvoidmain(String[]args)throwsInterruptedException{ EventLoopGroupworker=newNioEventLoopGroup(); Bootstrapb=newBootstrap(); b.group(worker) .channel(NioSocketChannel.class) .handler(newChannelInitializer(){ @Override protectedvoidinitChannel(SocketChannelsc)throwsException{ //ByteBufbuf=Unpooled.copiedBuffer("$_".getBytes()); //sc.pipeline().addLast(newDelimiterBasedFrameDecoder(1024,buf)); //sc.pipeline().addLast(newStringDecoder()); sc.pipeline().addLast(MarshallingCodeCFactory.buildMarshallingDecoder()); sc.pipeline().addLast(MarshallingCodeCFactory.buildMarshallingEncoder()); sc.pipeline().addLast(newClientHandler()); } }); ChannelFuturef=b.connect("127.0.0.1",8765).sync(); for(inti=1;i<=5;i++){ Sendsend=newSend(); send.setId(i); send.setMessage("message"+i); send.setName("name"+i); f.channel().writeAndFlush(send); } f.channel().closeFuture().sync(); worker.shutdownGracefully(); } }
ClientHandler端
publicclassClientHandlerextendsChannelHandlerAdapter{ @Override publicvoidexceptionCaught(ChannelHandlerContextctx,Throwablecause) throwsException{ cause.printStackTrace(); ctx.close(); } @Override publicvoidchannelRead(ChannelHandlerContextctx,Objectmsg) throwsException{ Receivereceive=(Receive)msg; System.out.println("server反馈:"+receive); } }
send类
publicclassSendimplementsSerializable{ /** *serialVersionUID:TODO(用一句话描述这个变量表示什么) * *@since1.0.0 */ privatestaticfinallongserialVersionUID=1L; privateIntegerid; privateStringname; privateStringmessage; publicIntegergetId(){ returnid; } publicvoidsetId(Integerid){ this.id=id; } publicStringgetName(){ returnname; } publicvoidsetName(Stringname){ this.name=name; } publicStringgetMessage(){ returnmessage; } publicvoidsetMessage(Stringmessage){ this.message=message; } @Override publicStringtoString(){ return"Send[id="+id+",name="+name+",message="+message+"]"; } }
Receive类
publicclassReceiveimplementsSerializable{ /** *serialVersionUID:TODO(用一句话描述这个变量表示什么) *@since1.0.0 */ privatestaticfinallongserialVersionUID=1L; privateIntegerid; privateStringname; privateStringmessage; privatebyte[]sss; publicbyte[]getSss(){ returnsss; } publicvoidsetSss(byte[]sss){ this.sss=sss; } publicIntegergetId(){ returnid; } publicvoidsetId(Integerid){ this.id=id; } publicStringgetName(){ returnname; } publicvoidsetName(Stringname){ this.name=name; } publicStringgetMessage(){ returnmessage; } publicvoidsetMessage(Stringmessage){ this.message=message; } @Override publicStringtoString(){ return"Receive[id="+id+",name="+name+",message="+message+",sss="+Arrays.toString(sss)+"]"; } }
注意:send类和receive这两个类,我们再真实环境开发的时候服务器和客户端往往是两个web应用程序,在这里我们要注意服务端和客户端之间的两个类类名和包名在两端要完全相同。
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对毛票票的支持。