1.创建服务端启动类 HelloWorldServer
package com.xw.server;
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.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import java.net.InetSocketAddress;
import com.xw.server.handler.HelloWorldServerHandler;
public class HelloWorldServer {
private int port;
public HelloWorldServer(int port) {
this.port = port;
}
public void start() {
EventLoopGroup bossGroup = new NioEventLoopGroup(1);
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
//创建服务器引导程序实例
ServerBootstrap sbs = new ServerBootstrap();
sbs.group(bossGroup, workerGroup)
//指定 NIO transport 指定端口
.channel(NioServerSocketChannel.class).localAddress(new InetSocketAddress(port))
//向通道管道中添加处理程序
.childHandler(new ChannelInitializer<SocketChannel>() {
protected void initChannel(SocketChannel ch) throws Exception {
// ch.pipeline().addLast("framer", new DelimiterBasedFrameDecoder(8192, Delimiters.lineDelimiter()));
//使用netty的 字符编码解码
ch.pipeline().addLast("decoder", new StringDecoder());
ch.pipeline().addLast("encoder", new StringEncoder());
//通道添加 输入的处理类
ch.pipeline().addLast(new HelloWorldServerHandler());
};
}).option(ChannelOption.SO_BACKLOG, 128).childOption(ChannelOption.SO_KEEPALIVE, true);
// 绑定端口,开始接收进来的连接
// 绑定服务器、等待服务器关闭并释放资源
ChannelFuture future = sbs.bind(port).sync();
System.out.println("Server start listen at " + port);
//等待服务器套接字关闭。
future.channel().closeFuture().sync();
} catch (Exception e) {
//关闭所有事件循环以终止所有线程。
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
public static void main(String[] args) throws Exception {
int port;
if (args.length > 0) {
port = Integer.parseInt(args[0]);
} else {
port = 8080;
}
new HelloWorldServer(port).start();
}
}
2.创建输入处理类
package com.xw.server.handler;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
//为什么在服务器中不使用SimpleChannelInboundHandler呢?因为服务器要返回相同的消息给客户端,在服务器执行完成写操作之前不能释放调
//用读取到的消息,因为写操作是异步的,一旦写操作完成后,Netty中会自动释放消息。
public class HelloWorldServerHandler extends ChannelInboundHandlerAdapter {
//数据读
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
System.out.println("channelRead");
System.out.println("channelRead"+ctx.channel().remoteAddress() + "->Server :" + msg.toString());
//反写客户端
ctx.write("server back write" + msg);
ctx.flush();
}
// //数据读
// //如果在 initChannel 中指定了编码解码就直接从MSG中获取 ,如果 没有指定,则可以通过bytebuf读取
// @Override
// public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
// ByteBuf buf = (ByteBuf) msg;
// byte[] req = new byte[buf.readableBytes()];
// buf.readBytes(req);
// try {
// String body = new String(req, "UTF-8");
// System.out.println("channelRead"+body);
// }catch (Exception e){
// e.printStackTrace();
// }
//
// String response = "server back write";
// ByteBuf resp = Unpooled.copiedBuffer(response.getBytes());
// ctx.write(resp);
//
// }
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
cause.printStackTrace();
ctx.close();
}
@Override
public void channelWritabilityChanged(ChannelHandlerContext ctx) throws Exception {
System.out.println("channelWritabilityChanged"+ctx.channel().remoteAddress());
}
//增加接入时候触发
@Override
public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
System.out.println("channelRegistered"+ctx.channel().remoteAddress());
}
//关闭通道时候触发 顺序3
@Override
public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
System.out.println("channelUnregistered"+ctx.channel().remoteAddress());
}
//关闭通道时触发 顺序2
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
System.out.println("channelInactive"+ctx.channel().remoteAddress());
}
//数据读完
//关闭通道时候触发 顺序1
@Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
System.out.println("channelReadComplete"+ctx.channel().remoteAddress());
}
@Override
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
System.out.println("userEventTriggered"+ctx.channel().remoteAddress());
}
}
3.测试控制台打印
Server start listen at 8080
channelRegistered/127.0.0.1:52118
channelRegistered/127.0.0.1:52120
channelRead
channelRead/127.0.0.1:52118->Server :1
channelReadComplete/127.0.0.1:52118
channelRead
channelRead/127.0.0.1:52120->Server :2
channelReadComplete/127.0.0.1:52120
channelReadComplete/127.0.0.1:52118
channelInactive/127.0.0.1:52118
channelUnregistered/127.0.0.1:52118
channelReadComplete/127.0.0.1:52120
channelInactive/127.0.0.1:52120
channelUnregistered/127.0.0.1:52120