Netty入门(2) Netty尝鲜
action 1 :编写一个应答服务器
首先对于netty的maven项目的搭建可以参考一下博客:
https://blog.csdn.net/qq_37421018/article/details/87802603
在这里我们用书中的例子体验一下netty的应答流程:
首先构建一个netty服务端,同时实现一个handler,handler可以理解为一个处理器,而且是自定义的, 在大多数场景中是不能够复用现有的实现完成处理:
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();
}
}
实现NettyServer的Handler–> SimpleHandler:
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);
}
}
接下来建立一个客户端来连接这个服务端,同时也完成他的handler:
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); //写进通道
}
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}finally {
group.shutdownGracefully(); //释放资源
}
}
}
客户端handler的实现–> ClientHandler,本质上使用的是channel的处理器,所以这里其实也是使用的响应的netty的handler适配器的接口 :
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());
}
}
服务端结果:
客户端结果:
- 写这个例子主要的目的就是体会下netty和其他的如Vertx创建服务端连接和客户端连接的区别,其次也是为了体会一下netty异步形式是如何在一个CS架构中使用的。
- 了解netty创建服务端以及客户端的流程。
参考资料:
Netty in Action
https://blog.csdn.net/u012150590/article/details/78908002