netty的依赖比较少,只需要引入以下就可以编写服务了
编写服务器 编写服务处理类EchoServerHandlerio.netty netty-all 4.1.22.Final
@Sharable
public class EchoServerHandler extends ChannelInboundHandlerAdapter {
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
cause.printStackTrace();
ctx.close();
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
ByteBuf in = (ByteBuf) msg;
System.out.println("server recieved: " + in.toString(CharsetUtil.UTF_8));
ctx.write(in);
}
@Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
ctx.writeAndFlush(Unpooled.EMPTY_BUFFER)
.addListener(ChannelFutureListener.CLOSE);
}
}
代码解读
该类处理真正的业务逻辑
要处理入栈消息,必须继承Channel,这里继承了ChannelInboundHandlerAdapter
这里需要重写三个方法,
exceptionCaught这个是异常处理的方法,当连接发生异常就会执行,在这里只是打印了错误信息然后将通道关闭了
channelRead方法是接收客户端传输过来的消息,netty传输的消息都是封装到ByteBuf对象的,在这里就直接获取这个对象,ChannelHandlerContext ctx是与客户端连接的通道,通过连接通道将客户端端的消息再发送回去,实现echo
channelReadComplete方法是读取消息完成后执行的方法
上面写好了业务类,现在我们要把业务类注册到服务器中,如下代码:
public class EchoServer {
private final int port = 6000;
public static void main(String[] args) throws InterruptedException {
EchoServer echoServer = new EchoServer();
System.out.println("server start ...");
echoServer.start();
}
public void start() throws InterruptedException {
EchoServerHandler serverHandler = new EchoServerHandler();
EventLoopGroup group = new NioEventLoopGroup();
ServerBootstrap b = new ServerBootstrap();
b.group(group).channel(NioServerSocketChannel.class).localAddress(new InetSocketAddress(port))
.childHandler(new ChannelInitializer() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(serverHandler);
}
});
try {
ChannelFuture f = b.bind().sync();
f.channel().closeFuture().sync();
} finally {
group.shutdownGracefully().sync();
}
}
}
编写客户端
编写客户端处理类EchoClientHandler
public class EchoClientHandler extends SimpleChannelInboundHandler代码解读{ @Override protected void channelRead0(ChannelHandlerContext ctx, ByteBuf msg) throws Exception { System.out.println("client received: " + msg.toString(CharsetUtil.UTF_8)); } @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { //连接后发送消息 ctx.writeAndFlush(Unpooled.copiedBuffer("Netty rocks!", CharsetUtil.UTF_8)); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { cause.printStackTrace(); ctx.close(); } }
和服务端一样,代码都需要编写服务类处理实际业务,继承SimpleChannelInboundHandler
重写如下几个方法:
channelActive是连接服务端的后做的事,在这里,就简单把"Netty rocks!"字符串发送过去
exceptionCaught是发生异常后执行的方法,这里只是简单打印了错误日志
channelRead0是接收服务端发送的消息,这里就是把服务端发送的消息简单打印一下
编写启动类,把业务类EchoClientHandler注册进去
public class EchoClient {
private String host = "localhost";
private int port = 6000;
public static void main(String[] args) throws InterruptedException {
new EchoClient().start();
}
public void start() throws InterruptedException {
EventLoopGroup group = new NioEventLoopGroup();
Bootstrap b = new Bootstrap();
b.group(group)
.channel(NioSocketChannel.class)
.remoteAddress(new InetSocketAddress(host,port))
.handler(new ChannelInitializer() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
// TODO Auto-generated method stub
ch.pipeline().addLast(new EchoClientHandler());
}
});
ChannelFuture f = b.connect().sync();
try {
f.channel().closeFuture().sync();
} finally {
group.shutdownGracefully().sync();
}
}
}
结语
这样我们就可以使用netty实现一个客户端发送消息给服务端后,服务端会原样将消息返回给客户端的服务。我们将这种服务叫做echo服务。



