通过java进行网络编程,netty可以提高网络通信的开发效率的同时大大提高网络通信的效率。下面来看下如何使用netty进行高效编程。
引入依赖
<dependency>
<groupId>io.netty</gro
<artifactId>netty-all</artifactId>
<version>4.0.25.Final</version>
</dependency>
netty3和netty4在编程api上有一定的区别,本篇是通过netty4进行实践的。
服务端句柄对象io.netty.bootstrap.ServerBootstrap
netty服务端和客户端的创建都是依赖于Bootstrap
句柄对象,下面我们看下服务端是如何通过ServerBootstrap创建服务的。
serverBootstrap.group(new NioEventLoopGroup(), new NioEventLoopGroup()).channel(NioServerSocketChannel.class)
.localAddress(new InetSocketAddress(nettyServerConfig.getListenPort()))
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
public void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(
new NettyEncoder(),
new NettyDecoder(),
new NettyConnetManageHandler(),
new EchoServerHandler());
}
});
ChannelFuture f = serverBootstrap.bind().sync();
大家去看源码就可以知道上面都是在初始化ServerBootstrap对象的属性:
io.netty.bootstrap.ServerBootstrap#group(io.netty.channel.EventLoopGroup, io.netty.channel.EventLoopGroup)
第一个参数是用于接收请求的EventLoopGroup,第二个参数是处理请求的EventLoopGroup。io.netty.bootstrap.AbstractBootstrap#channel
用于初始化channelFactory,channel创建为NioServerSocketChannel的类型。io.netty.bootstrap.AbstractBootstrap#localAddress(java.net.SocketAddress)
这个没什么好说的设置监听的地址。io.netty.bootstrap.ServerBootstrap#childHandler
数据流的handler处理器,上面我们设置了四个handler,分别有数据流出和流进是待处理的handler链。上面都是在初始化句柄接下来,
serverBootstrap.bind().sync()
同步开启服务。
客户端句柄对象io.netty.bootstrap.Bootstrap
bootstrap.group(new NioEventLoopGroup()).channel(NioSocketChannel.class)
.handler(new ChannelInitializer<SocketChannel>() {
@Override
public void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(
new NettyEncoder(),
new NettyDecoder(),
new NettyClientHandler());
}
});
bootstrap.connect(new InetSocketAddress(ip, port));
客户端句柄初始化相对来说简单,初始化处理EventLoopGroup,channel factory,handler处理链,最后connect就可以连接到netty的服务端了。
handler实现
1、NettyEncoder
public class NettyEncoder extends MessageToByteEncoder<NettyCommand> {
@Override
public void encode(ChannelHandlerContext ctx, NettyCommand msg, ByteBuf out)
throws Exception {
out.writeBytes(msg.encode());
}
}
2、NettyDecoder
public class NettyDecoder extends ByteToMessageDecoder {
@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
byte[] tmpBuf = new byte[in.readableBytes()];
in.readBytes(tmpBuf);
NettyCommand command = new NettyCommand();
out.add(command.decode(tmpBuf));
}
}
传输对象的encode和decode都依赖于自定义的NettyCommand进行定义。
3、EchoServerHandler
class EchoServerHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
System.out.println("phase: channelReadComplete");
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx,
Throwable cause) {
System.out.println("phase: exceptionCaught");
cause.printStackTrace();
ctx.close();
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
NettyCommand requestCommand = (NettyCommand) msg;
System.out.println("Server received: " + new String(requestCommand.getBody()));
processMessageReceive(ctx, requestCommand);
}
}
4、NettyClientHandler
class NettyClientHandler extends SimpleChannelInboundHandler<NettyCommand> {
@Override
public void channelActive(ChannelHandlerContext ctx) {
System.out.println("channelActive");
}
@Override
protected void channelRead0(ChannelHandlerContext ctx, NettyCommand msg)
throws Exception {
NettyCommand command = (NettyCommand) msg;
processMessageReceive(ctx, command);
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx,
Throwable cause) { //4
System.out.println("exceptionCaught");
cause.printStackTrace();
ctx.close();
}
@Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
System.out.println("channelReadComplete");
}
}
到这里一个简单的hello netty就实现完毕了。
后记
到这里整个脑袋还不是太清晰,可能是因为初次使用netty,很多深入的原理性东西还没有充分的认识到,后面不断学习升华。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。