前面文章讲了如何通过Netty3写一个简单的例子,但是Netty4和Netty5同Netty3有很大的不同,这篇文章简单介绍下如何通过Netty5写一个简单的服务端和客户端例子。
服务端
1. 初始化一个NIO辅助服务类
//NIO服务的辅助启动类
ServerBootstrap bootstrap = new ServerBootstrap();
2. 初始化两个处理IO操作的多线程事件循环器,一个用于接收连接,一个用于处理客户端i/o事件
//boss和worker
//EventLoopGroup是用来处理IO操作的多线程事件循环器
//负责接收客户端连接线程
EventLoopGroup boss = new NioEventLoopGroup();
//负责处理客户端i/o事件、task任务、监听任务组
EventLoopGroup worker = new NioEventLoopGroup();
3. 设置服务端服务类的一些参数,包括channel绑定,事件循环器绑定等
//设置线程池
bootstrap.group(boss, worker);
//配置 Channel
bootstrap.channel(NioServerSocketChannel.class);
bootstrap.childHandler(new ChannelInitializer<Channel>() {
protected void initChannel(Channel ch) throws Exception {
ch.pipeline().addLast(new StringDecoder());
ch.pipeline().addLast(new StringEncoder());
ch.pipeline().addLast(new ServerHanler());
}
});
//BACKLOG用于构造服务端套接字ServerSocket对象,
// 标识当服务器请求处理线程全满时,用于临时存放已完成三次握手的请求的队列的最大长度
bootstrap.option(ChannelOption.SO_BACKLOG, 2048);
//是否启用心跳保活机制
bootstrap.childOption(ChannelOption.SO_KEEPALIVE, true);
bootstrap.childOption(ChannelOption.TCP_NODELAY, true);
这里注册了一个自定义的事件处理的类ServerHanler,该类继承于SimpleChannelInboundHandler<String>,ServerHanler主要处理代码如下:
@Override
protected void messageReceived(ChannelHandlerContext ctx, String msg) throws Exception {
System.out.println(msg);
ctx.channel().writeAndFlush("hi");
ctx.writeAndFlush("hi");
}
4. 绑定端口,开始监听连接,并阻塞主线程退出
ChannelFuture future = bootstrap.bind(10010);
System.out.println("start");
//服务器关闭监听
/*channel.closeFuture().sync()实际是如何工作:
channel.closeFuture()不做任何操作,只是简单的返回channel对象中的closeFuture对象,对于每个Channel对象,都会有唯一的一个CloseFuture,用来表示关闭的Future,
所有执行channel.closeFuture().sync()就是执行的CloseFuturn的sync方法,从上面的解释可以知道,这步是会将当前线程阻塞在CloseFuture上*/
future.channel().closeFuture().sync();
客户端
1. 初始化一个NIO辅助服务类
//服务类
Bootstrap bootstrap=new Bootstrap();
2. 初始化一个处理IO操作的多线程循环处理器
//worker
EventLoopGroup worker=new NioEventLoopGroup();
3. 设置NIO辅助类的一些属性,包括指定多线程循环处理器、指定channel和指定初始化处理操作
//设置IO多线程循环处理器
bootstrap.group(worker);
//设置Channel
bootstrap.channel(NioSocketChannel.class);
//指定客户端初始化处理操作
bootstrap.handler(new ChannelInitializer<Channel>() {
@Override
protected void initChannel(Channel ch) throws Exception{
ch.pipeline().addLast(new StringDecoder());
ch.pipeline().addLast(new StringEncoder());
ch.pipeline().addLast(new ClientHandler());
}
});
此处有一个处理消息的自定义类ClientHandler,继承自SimpleChannelInboundHandler<String>,ClientHandler主要代码如下:
@Override
protected void messageReceived(ChannelHandlerContext ctx, String msg) throws Exception {
System.out.println("客户端收到消息:"+msg);
}
4. 开始连接服务端
ChannelFuture connect=bootstrap.connect("127.0.0.1",10010);
5.开始进行发送消息
BufferedReader bufferedReader=new BufferedReader(new InputStreamReader(System.in));
while (true){
System.out.println("请输入:");
String msg= bufferedReader.readLine();
connect.channel().writeAndFlush(msg);
}