Netty提供异步的、事件驱动的网络应用程序框架和工具,用以快速开发高性能、高可靠性的网络服务器和客户端程序。我们在网络编程的时候一般都会使用该框架作为基础框架,下面使用netty来实现简单的群聊系统来认识netty的基本使用方法。
服务端:
public class GroupChatServer { private int port;//定义端口信息 private GroupChatServer(int port){ this.port = port; } private void run() throws Exception{ NioEventLoopGroup bossGroup = new NioEventLoopGroup(); NioEventLoopGroup workGroup = new NioEventLoopGroup(8); try { ServerBootstrap serverBootstrap = new ServerBootstrap(); serverBootstrap.group(bossGroup,workGroup) .channel(NioServerSocketChannel.class)//设置服务端的通道信息 .option(ChannelOption.SO_BACKLOG,128)//设置线程队列连接个数 .childOption(ChannelOption.SO_KEEPALIVE,true)//设置活动保持连接的状态 .childHandler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel socketChannel) throws Exception { ChannelPipeline pipeline = socketChannel.pipeline(); //添加对消息处理的编解码器 pipeline.addLast(new StringEncoder());//编码器 pipeline.addLast(new StringDecoder());//解码器 pipeline.addLast(new GroupChatServerHandler());//自定义处理器 } }); System.out.println("服务端ok..............."); //绑定端口 ChannelFuture channelFuture = serverBootstrap.bind(port).sync(); //添加对异步处理的监听机制 channelFuture.addListener(new ChannelFutureListener() { @Override public void operationComplete(ChannelFuture channelFuture) throws Exception { if(channelFuture.isDone()){ System.out.println("操作完成..."); }else{ System.out.println("操作没有完成"); } if(channelFuture.isSuccess()){ System.out.println("操作成功..."); }else{ System.out.println("操作失败..."); } } }); channelFuture.channel().closeFuture().sync(); }finally { bossGroup.shutdownGracefully(); workGroup.shutdownGracefully(); } } public static void main(String[] args) throws Exception{ new GroupChatServer(8088).run(); } } 服务端对于的handler:
public class GroupChatServerHandler extends SimpleChannelInboundHandler<String> { //定义一个管道组来处理所有的管道信息 //GlobalEventExecutor.INSTANCE一个单列的全局事件处理器 private static ChannelGroup channelGroup = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE); //定义事件格式化工具 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); /** * 建立连接会触发该方法,用来在客户端提示某某某上线 * @param ctx * @throws Exception */ @Override public void handlerAdded(ChannelHandlerContext ctx) throws Exception { Channel channel = ctx.channel(); channelGroup.writeAndFlush("客户端:" + ctx.channel().remoteAddress() + "上线了..."); channelGroup.add(channel);//把新加入的管道添加到管道组 } /** * 客户端离开连接,该方法被触发 * @param ctx * @throws Exception */ @Override public void handlerRemoved(ChannelHandlerContext ctx) throws Exception { Channel channel = ctx.channel(); channelGroup.writeAndFlush("客服端:" + channel.remoteAddress() + "下线了..."); } /** * 表示channel活动状态,在服务端提示某某某上线了 * @param ctx * @throws Exception */ @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { System.out.println(ctx.channel().remoteAddress()+"上线了........"); } /** * 表示channel不活动状态,在服务端提示某某是离线了 * @param ctx * @throws Exception */ @Override public void channelInactive(ChannelHandlerContext ctx) throws Exception { System.out.println(ctx.channel().remoteAddress()+"离线了........"); } /** * 处理信息并且转发 * @param channelHandlerContext * @param msg * @throws Exception */ @Override protected void channelRead0(ChannelHandlerContext channelHandlerContext, String msg) throws Exception { Channel channel1 = channelHandlerContext.channel(); System.out.println("用户:" + channel1.remoteAddress() + "发送的信息为:" + msg); //开始转发信息 for (Channel channel : channelGroup) { if (channel != channel1) { channel.writeAndFlush(sdf.format(new Date()) + "用户:" + channel1.remoteAddress() + "发送的信息为:" + msg); } } } /** * 处理异常信息 * @param ctx * @param cause * @throws Exception */ @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { ctx.close(); } } |
客户端对于代码:
public class GroupCharClient { //定义端口号和ip地址信息 private int port; private String host; /** * 定义加载ip地址和端口号的方法 */ public GroupCharClient(String host,int port){ this.host = host; this.port = port; } /** * 定义客户端运行的方法 */ public void run(){ NioEventLoopGroup group = new NioEventLoopGroup(); try { //定义客户端启动的方法 Bootstrap bootstrap = new Bootstrap(); bootstrap.group(group) .channel(NioSocketChannel.class) .handler(new ChannelInitializer<SocketChannel>() { protected void initChannel(SocketChannel socketChannel) throws Exception { //定义编解码器 ChannelPipeline pipeline = socketChannel.pipeline(); pipeline.addLast(new StringDecoder());//加入解码器 pipeline.addLast(new StringEncoder());//加入编码器 //加入自己的handler pipeline.addLast(new GroupCharClientHandler()); } }); System.out.println("客户上线了..."); //绑定端口连接 ChannelFuture channelFuture = bootstrap.connect(host, port).sync(); Channel channel = channelFuture.channel(); //客户端输入的信息 Scanner scanner = new Scanner(System.in); while(scanner.hasNextLine()){ String msg = scanner.next(); channel.writeAndFlush(msg); } } catch (Exception e) { e.printStackTrace(); } finally { group.shutdownGracefully(); } } public static void main(String[] args) { new TestGroupChatClient("127.0.0.1",8088).run(); } } 客户度对于的handler: public class GroupCharClientHandler extends SimpleChannelInboundHandler<String> { /** * 读取服务端转发的消息 * @param channelHandlerContext * @param s * @throws Exception */ protected void channelRead0(ChannelHandlerContext channelHandlerContext, String s) throws Exception { System.out.println("服务端:" + channelHandlerContext.channel().remoteAddress()+"转发的消息为:"+ s); } } |