本例使用 String 编码解码器处理类
服务器端:
public class Server {
private static final int port = 10086;
public void startup() throws InterruptedException {
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workerGroup);
b.channel(NioServerSocketChannel.class);
b.childHandler(new ServerHandlerInitializer());
// 绑定端口启动服务
ChannelFuture f = b.bind(port).sync();
// 监听服务器关闭
f.channel().closeFuture().sync();
} finally {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
public static void main(String[] args) throws InterruptedException {
new Server().startup();
}
}
ServerHandlerInitializer:
public class ServerHandlerInitializer extends ChannelInitializer<SocketChannel> {
// ChannelPipeline 的执行顺序, 举例说明(官方文档)
// p.addLast("1", new InboundHandlerA());
// p.addLast("2", new InboundHandlerB());
// p.addLast("3", new OutboundHandlerA());
// p.addLast("4", new OutboundHandlerB());
// p.addLast("5", new InboundOutboundHandlerX());
// 如果是接收,执行顺序:1,2,5 (实现 ChannelInboundHandler 的处理类)
// 如果是流出,执行顺序:5,4,3 (实现 ChannelOutboundHandler 的处理类)
@Override
protected void initChannel(SocketChannel ch) throws Exception {
// 以("\n")为结尾分割的解码器
ch.pipeline().addLast(new DelimiterBasedFrameDecoder(8192, Delimiters.lineDelimiter()));
// 字符解码器
ch.pipeline().addLast(new StringDecoder());
// 字符编码器
ch.pipeline().addLast(new StringEncoder());
// 自定义
ch.pipeline().addLast(new ServerHandler());
}
}
ServerHandler:
public class ServerHandler extends SimpleChannelInboundHandler<String> {
// 接收到新数据时
@Override
protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
// 接收信息
System.out.println(ctx.channel().remoteAddress() + " : " + msg);
// 返回客户端消息, \n 是必须的, 客户端接受时也使用 DelimiterBasedFrameDecoder 判断结束位置
ctx.writeAndFlush("Received your message !\n");
}
// 客户端连接时触发
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
System.out.println("RamoteAddress : " + ctx.channel().remoteAddress() + " connected !");
ctx.writeAndFlush( "Welcome!\n");
}
}
客户端:
public class Client {
private String host;
private int port;
public Client(String host, int port) {
this.host = host;
this.port = port;
}
public void connect() throws Exception {
EventLoopGroup group = new NioEventLoopGroup();
try {
Bootstrap b = new Bootstrap();
b.group(group);
b.channel(NioSocketChannel.class);
b.handler(new ClientHandlerInitializer());
// 连接服务器
Channel ch = b.connect(host, port).sync().channel();
// 接受系统输入
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
// 连续输入
while (true) {
String line = in.readLine();
if (line == null) // 如果是空行, 则跳过本次循环, 不输出
continue;
ch.writeAndFlush(line + "\r\n");
}
} finally {
group.shutdownGracefully();
}
}
public static void main(String[] args) throws Exception {
new Client("localhost", 10086).connect();
}
}
ClientHandlerInitializer:
public class ClientHandlerInitializer extends ChannelInitializer<SocketChannel> {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
// 编码解码需和服务器端对应
ch.pipeline().addLast(new DelimiterBasedFrameDecoder(8192, Delimiters.lineDelimiter()));
ch.pipeline().addLast(new StringDecoder());
ch.pipeline().addLast(new StringEncoder());
ch.pipeline().addLast(new ClientHandler());
}
}
ClientHandler:
public class ClientHandler extends SimpleChannelInboundHandler<String> {
// 处理服务器响应
@Override
protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
System.out.println("Server : " + msg);
}
}