总结一下自己学习一个新事物(技术层面的)的心得体会,首先了解它是做什么的(what),其次学习使用它(how),最后了解它内部如何实现(why)。当然这个是需要一个漫长的过程的,顺序也是循序渐进的。
学习Netty之前需要有一定的网络编程基础,如果对网络编程不太熟悉的,可以先看看Java网络编程系列
Netty简介
Netty是由JBOSS提供的一个开源的java网络编程框架,主要是对java的nio包进行了再次封装。Netty比java原生的nio包提供了更加强大、稳定的功能和易于使用的api。 netty的作者是Trustin Lee,这是一个韩国人,他还开发了另外一个著名的网络编程框架,mina。二者在很多方面都十分相似,它们的线程模型也是基本一致 。不过netty社区的活跃程度要mina高得多。
Netty的应用案例:
- apache storm ,这是一个分布式实时计算框架
- hadoop,其RPC框架Avro就使用了Netty作为底层通信框架
- apache rocketmq,这是阿里巴巴的一个消息中间件,现在已经捐赠给apache了
- apache dubbo,这是阿里巴巴开发的一个SOA服务治理框架
……
版本依赖
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.22.Final</version>
</dependency>
Server 端
package com.github.sources.network.netty.base;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import java.net.InetSocketAddress;
/**
*
*/
public class HelloWorldServer {
private int port;
public static void main(String[] args){
new HelloWorldServer(8080).start();
}
public HelloWorldServer(int port) {
this.port = port;
}
public void start() {
/**
* 创建两个EventLoopGroup,即两个线程池,boss线程池用于接收客户端的连接,一个线程监听一个端口,一般只会监听一个端口所以只需一个线程
* work池用于处理网络连接数据读写或者后续的业务处理(可指定另外的线程处理业务,work完成数据读写)
*/
EventLoopGroup boss = new NioEventLoopGroup(1);
EventLoopGroup work = new NioEventLoopGroup();
try {
/**
* 实例化一个服务端启动类,
* group()指定线程组
* channel()指定用于接收客户端连接的类,对应java.nio.ServerSocketChannel
* childHandler()设置编码解码及处理连接的类
*/
ServerBootstrap server = new ServerBootstrap().group(boss, work).channel(NioServerSocketChannel.class)
.localAddress(new InetSocketAddress(port)).option(ChannelOption.SO_BACKLOG, 128).childOption(ChannelOption.SO_KEEPALIVE, true)
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ch.pipeline()
.addLast("decoder", new StringDecoder())
.addLast("encoder", new StringEncoder())
.addLast(new HelloWorldServerHandler());
}
});
//绑定端口
ChannelFuture future = server.bind().sync();
System.out.println("server started and listen " + port);
future.channel().closeFuture().sync();
} catch (Exception e) {
e.printStackTrace();
}finally {
boss.shutdownGracefully();
work.shutdownGracefully();
}
}
public static class HelloWorldServerHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
System.out.println("HelloWorldServerHandler active");
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
System.out.println("server channelRead..");
System.out.println(ctx.channel().remoteAddress()+"->Server :"+ msg.toString());
ctx.write("server write"+msg);
ctx.flush();
}
}
}
Client端
package com.github.sources.network.netty.base;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
/**
*
*/
public class HelloWorldClient {
private static final String HOST = "127.0.0.1";
private static final int PORT= 8080;
public static void main(String[] args){
new HelloWorldClient().start(HOST, PORT);
}
public void start(String host, int port) {
EventLoopGroup group = new NioEventLoopGroup();
try {
Bootstrap client = new Bootstrap().group(group).channel(NioSocketChannel.class)
.option(ChannelOption.TCP_NODELAY, true).handler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ch.pipeline()
.addLast("decoder", new StringDecoder())
.addLast("encoder", new StringEncoder())
.addLast(new HelloWorldClientHandler());
}
});
ChannelFuture future = client.connect(host, port).sync();
future.channel().writeAndFlush("Hello Netty Server ,I am a netty client");
future.channel().closeFuture().sync();
} catch (Exception e) {
e.printStackTrace();
} finally {
group.shutdownGracefully();
}
}
public static class HelloWorldClientHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
System.out.println("HelloWorldClientHandler Active");
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
System.out.println("HelloWorldClientHandler read Message:"+msg);
}
}
}