Netty——简单创建服务器、客户端通讯
Netty 是一个基于NIO的客户、服务器端编程框架,使用Netty 可以确保你快速和简单的开发出一个网络应用,例如实现了某种协议的客户,服务端应用。Netty相当简化和流线化了网络应用的编程开发过程,例如,TCP和UDP的socket服务开发。
Netty简单来说就是socket通讯,支持多协议的通讯
对 创建 netty 的过程作了详细的解析
1、简单创建一个Netty服务器
package com.netty.test; import java.net.InetAddress; import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; 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; /** * Netty4 服务端代码 * */ public class HelloWorldServer { public static void main(String[] args) { // EventLoop 代替原来的 ChannelFactory EventLoopGroup bossGroup = new NioEventLoopGroup(); EventLoopGroup workerGroup = new NioEventLoopGroup(); try {
ServerBootstrap serverBootstrap = new ServerBootstrap(); //创建 一个netty 服务器 // server端采用简洁的连写方式,client端才用分段普通写法。 serverBootstrap.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) // 指定channel[通道]类型 .childHandler(new ChannelInitializer<SocketChannel>() { // 指定Handler [操纵者]
@Override public void initChannel(SocketChannel ch) throws Exception { // 以("\n")为结尾分割的 解码器 ch.pipeline().addLast("framer", new DelimiterBasedFrameDecoder(8192, Delimiters.lineDelimiter())); // 字符串 解码 和 编码 默认的 StringDecoder 字符串形式输出 ch.pipeline().addLast("decoder", new StringDecoder()); ch.pipeline().addLast("encoder", new StringEncoder()); ch.pipeline().addLast(new HelloServerHandler()); // 添加自己的对 上传数据的处理 }
}).option(ChannelOption.SO_KEEPALIVE, true);
ChannelFuture f = serverBootstrap.bind(8000).sync(); // 绑定 8000 端口 f.channel().closeFuture().sync(); } catch (InterruptedException e) { } finally { workerGroup.shutdownGracefully(); // 销毁 netty bossGroup.shutdownGracefully(); } } /** * 自己对 处理数据 * * @author flm * 2017年11月10日 */ private static class HelloServerHandler extends ChannelInboundHandlerAdapter { @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { // 收到消息直接打印输出 System.out.println(ctx.channel().remoteAddress() + " Say : " + msg); // 返回客户端消息 - 我已经接收到了你的消息 ctx.writeAndFlush("server Received your message !\n"); } /* * * 覆盖 channelActive 方法 在channel被启用的时候触发 (在建立连接的时候) * * channelActive 和 channelInActive 在后面的内容中讲述,这里先不做详细的描述 */ @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { System.out.println("RamoteAddress : " + ctx.channel().remoteAddress() + " active !"); ctx.writeAndFlush("Welcome to " + InetAddress.getLocalHost().getHostName() + " service!\n"); //回复 super.channelActive(ctx); } }
2、netty 客户端 创建
package com.netty.test; import java.net.InetSocketAddress; import java.util.Date; import io.netty.bootstrap.Bootstrap; import io.netty.channel.Channel; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelPipeline; 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; /** * Netty4 客户端代码 * */ public class HelloWorldClient { public static void main(String args[]) { // Bootstrap,且构造函数变化很大,这里用无参构造。 Bootstrap bootstrap = new Bootstrap(); // 指定channel[通道]类型 bootstrap.channel(NioSocketChannel.class); // 指定Handler [操纵者] bootstrap.handler(new ChannelInitializer<Channel>() { @Override protected void initChannel(Channel ch) throws Exception { ChannelPipeline pipeline = ch.pipeline(); /* * 这个地方的 必须和服务端对应上。否则无法正常解码和编码 * */ pipeline.addLast("framer", new DelimiterBasedFrameDecoder(8192, Delimiters.lineDelimiter())); pipeline.addLast("decoder", new StringDecoder()); pipeline.addLast("encoder", new StringEncoder()); // 客户端的逻辑,自己对数据处理 pipeline.addLast(new HelloClientHandler()); } }); // 指定EventLoopGroup [事件 组] bootstrap.group(new NioEventLoopGroup()); // 连接到本地的8000端口的服务端 bootstrap.connect(new InetSocketAddress("127.0.0.1", 8000)); } /** * 客户端的逻辑,自己对数据处理 * * @author flm * 2017年11月10日 */ private static class HelloClientHandler extends ChannelInboundHandlerAdapter { /* * 监听 服务器 发送来的数据 */ @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { System.out.println("Server say : " + msg.toString()); } /* * 启动客户端 时触发 */ @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { System.out.println("Client active "); ctx.writeAndFlush("我是 client " + new Date() + "\n"); super.channelActive(ctx); } /* * 关闭 客户端 触发 */ @Override public void channelInactive(ChannelHandlerContext ctx) throws Exception { System.out.println("Client close "); super.channelInactive(ctx); } } }