netty 官方API: http://netty.io/4.1/api/index.html
netty 中文指南:https://waylau.com/netty-4-user-guide/ (来自个人)
首先 maven
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>5.0.0.Alpha2</version>
</dependency>
入门实例 分为一个数据处理类DiscardServerHandle 和一个 服务端实现类DiscardServer
DiscardServer(本来是扔掉所有输入数据的 后来觉得不直观 改为打印,这是一个简单的数据处理类 利用handle类来构造的数据处理服务器)
package demo;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
public class DiscardServer {
private int port;
public DiscardServer(int port) {
super();
this.port=port;
}
public void run() throws Exception {
//初始化 其中boss用来监控tcp链接,worker用来处理io事件.
//NioEventLoopGroup可以理解为一个线程池,内部维护了一组线程,每个线程负责处理多个Channel上的事件,而一个Channel只对应于一个线程,这样可以回避多线程下的数据同步问题。
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();
System.out.println("准备运行端口:"+port);
try {
//ServerBootstrap 这是一个对服务端做配置和启动的类
ServerBootstrap b = new ServerBootstrap();
b=b.group(bossGroup,workerGroup);
b=b.channel(NioServerSocketChannel.class);
b=b.childHandler(new ChannelInitializer<SocketChannel>() {
protected void initChannel(SocketChannel ch) throws Exception {
//根据数据处理类discardhandler来构造服务端
ch.pipeline().addLast(new DiscardServerHandler());
}
});
/*so_backlog so_keepalive都是socket的标准参数,并不是netty自己的。 BACKLOG用于构造服务端套接字ServerSocket对象,标识当服务器请求处理线程全满时,用于临时存放已完成三次握手的请求的队列的最大长度。如果未设置或所设置的值小于1,Java将使用默认值50。是否启用心跳保活机制。在双方TCP套接字建立连接后(即都进入ESTABLISHED状态)并且在两个小时左右上层没有任何数据传输的情况下,这套机制才会被激活。*/
b=b.option(ChannelOption.SO_BACKLOG, 128
);
b=b.childOption(ChannelOption.SO_KEEPALIVE, true);
ChannelFuture f = b.bind(port).sync();
f.channel().closeFuture().sync();
} catch (Exception e) {
// TODO: handle exception
} finally {
workerGroup.shutdownGracefully();
bossGroup.shutdownGracefully();
}
}
public static void main(String[] args) throws Exception {
int port;
if(args.length>0) {
port=Integer.parseInt(args[0]);
}else {
port =8080;
}
new DiscardServer(port).run();
System.out.println("server running");
}
}
DiscardServerHandler类
package demo;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerAdapter;
import io.netty.channel.ChannelHandlerContext;
import io.netty.util.ReferenceCountUtil;
public class DiscardServerHandler extends ChannelHandlerAdapter {
public void channelRead(ChannelHandlerContext ctx,Object msg) {
ByteBuf in = (ByteBuf) msg;
try {
while (in.isReadable()) {
System.out.print((char) in.readByte());
System.out.flush();
}
} finally {
ReferenceCountUtil.release(msg);
}
}
/*因于Netty的I/O异常或一个处理器实现的内部异常。多数情况下,捕捉到的异常应当被记录下来,并在这个方法中关闭这个channel通道。当然处理这种异常情况的方法实现可能因你的实际需求而有所不同,例如,在关闭这个连接之前你可能会发送一个包含了错误码的响应消息。*/
public void exceptionCaught(ChannelHandlerContext ctx,Throwable cause) throws Exception{
cause.printStackTrace();
ctx.close();
}
}
运行main方法之后 可以借助这个工具 来测试输入