0.Netty简介
Netty是最流行的NIO框架,它的健壮性、功能、性能、可定制性和可扩展性在同类框架都是首屈一指的。它已经得到成百上千的商业/商用项目验证,如Hadoop的RPC框架Avro、RocketMQ以及主流的分布式通信框架Dubbox等等。
1.服务端
import io.netty.bootstrap.Bootstrap;
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;
import io.netty.handler.codec.DelimiterBasedFrameDecoder;
import io.netty.handler.codec.Delimiters;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
public class NettyServer {
public static void main(String[] args) {
// TODO Auto-generated method stub
EventLoopGroup parentGroup=new NioEventLoopGroup();//设置boss线程
EventLoopGroup childGroup=new NioEventLoopGroup();// 设置worker线程
try {
ServerBootstrap serverBootstrap=new ServerBootstrap();//设置服务类
serverBootstrap.group(parentGroup, childGroup); //设置线程池
serverBootstrap.channel(NioServerSocketChannel.class); //设置socket工厂
//设置参数,TCP参数
serverBootstrap.option(ChannelOption.SO_BACKLOG, 2048)//serverSocketchannel的设置,链接缓冲池的大小
.childOption(ChannelOption.SO_KEEPALIVE, true)//socketchannel的设置,维持链接的活跃,清除死链接
.childOption(ChannelOption.TCP_NODELAY, true)//socketchannel的设置,关闭延迟发送
.childHandler(new ChannelInitializer<SocketChannel >() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
// TODO Auto-generated method stub
// ch.pipeline().addLast(new DelimiterBasedFrameDecoder(Integer.MAX_VALUE, Delimiters.lineDelimiter()[0]));
ch.pipeline().addLast(new StringDecoder()); //解码器
ch.pipeline().addLast(new StringEncoder()); //编码器
ch.pipeline().addLast(new SimpleHandler()); //自定义处理器
}
});
ChannelFuture future= serverBootstrap.bind(8080).sync(); //绑定端口
future.channel().closeFuture().sync(); //等待服务端关闭
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}finally {
//释放资源
parentGroup.shutdownGracefully();
childGroup.shutdownGracefully();
}
}
}
接着是自定义处理器类
import java.nio.charset.Charset;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
public class SimpleHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
// TODO Auto-generated method stub
System.out.println("服务端开始读取数据======");
System.out.println((String)msg);
ctx.channel().writeAndFlush("hello,client"); //回写数据给客户端
}
@Override
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
// TODO Auto-generated method stub
super.userEventTriggered(ctx, evt);
}
}
2.客户端
import java.nio.charset.Charset;
import java.util.Scanner;
import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.PooledByteBufAllocator;
import io.netty.channel.Channel;
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.nio.NioSocketChannel;
import io.netty.handler.codec.DelimiterBasedFrameDecoder;
import io.netty.handler.codec.Delimiters;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.util.AttributeKey;
public class NettyClient {
//静态化客户端初始设置
public static EventLoopGroup group=null;
public static Bootstrap bootstrap=null;
static {
group=new NioEventLoopGroup(); //设置worker线程
bootstrap=new Bootstrap(); //设置服务类
bootstrap.channel(NioSocketChannel.class); //设置工厂
bootstrap.group(group); //设置线程池
bootstrap.option(ChannelOption.SO_KEEPALIVE, true) //设置管道
.handler(new ChannelInitializer<Channel>() {
@Override
protected void initChannel(Channel ch) throws Exception {
// TODO Auto-generated method stub
// ch.pipeline().addLast(new DelimiterBasedFrameDecoder(Integer.MAX_VALUE, Delimiters.lineDelimiter()[0]));
ch.pipeline().addLast(new StringDecoder()); //译码器
ch.pipeline().addLast(new StringEncoder()); //编码器
ch.pipeline().addLast(new ClientHandler()); //自定义处理器
}
});
}
public static void main(String[] args) {
// TODO Auto-generated method stub
EventLoopGroup group=new NioEventLoopGroup();
try {
ChannelFuture future=bootstrap.connect("localhost",8080).sync(); //获取连接
Scanner in=new Scanner(System.in);
System.out.println("请输入内容给服务端:");
while(in.hasNext()) { //输入
String person=in.nextLine();
future.channel().writeAndFlush(person); //写进通道
}
/*ByteBuf buf=PooledByteBufAllocator.DEFAULT.buffer();
buf.writeBytes(person.getBytes(Charset.defaultCharset()));
future.channel().writeAndFlush(buf);*/
//future.channel().writeAndFlush(person);
//future.channel().writeAndFlush(Delimiters.lineDelimiter()[0]);
// future.channel().closeFuture().sync();
// Object result=future.channel().attr(AttributeKey.valueOf("ChannelKey")).get();
// System.out.println("haha========"+result);
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}finally {
group.shutdownGracefully(); //释放资源
}
}
}
接着是客户端自定义类
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.util.AttributeKey;
public class ClientHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
// TODO Auto-generated method stub
System.out.println("客户端开始读取数据");
System.out.println("接收到服务器数据为:"+msg.toString());
// ctx.channel().attr(AttributeKey.valueOf("ChannelKey")).set(msg.toString());
// ctx.channel().close();
}
}
3.运行结果