之前使用Mina框架,了解到Netty,号称高效,简洁,快速,更优于Mina。就让我忍不住开始倒腾一番。Netty是由JBOSS提供的一个java开源框架。Netty提供异步的、事件驱动的网络应用程序框架和工具,用以快速开发高性能、高可靠性的网络服务器和客户端程序。Netty 是一个基于NIO的客户,服务器端编程框架,使用Netty 可以确保你快速和简单的开发出一个网络应用。
还是老一套,先到官网弄个example跑跑,跑通了,看看代码,再去深入原理。以下就是我从官网弄过来的例子,稍有更改。
依赖:jdk1.7,netty5.0.0.Alpha2
开发环境:ideaIU-14.1.4
测试环境:win7
建立maven工程NettyDemo,在pom.xml配置文件添加必要的依赖:
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>NettyDemo</groupId> <artifactId>NettyDemo</artifactId> <version>1.0-SNAPSHOT</version> <dependencies> <dependency> <groupId>io.netty</groupId> <artifactId>netty-all</artifactId> <version>5.0.0.Alpha2</version> </dependency> </dependencies> </project>
SimpleChatClientHandle.java类:
package com.mangocool.netty; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.SimpleChannelInboundHandler; /** * Created by MANGOCOOL on 2015/10/30. */ public class SimpleChatClientHandler extends SimpleChannelInboundHandler<String> { // 优先级高于messageReceived方法,有了这个方法就会屏蔽messageReceived方法 // @Override // public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { // System.out.println(msg.toString()); // } @Override protected void messageReceived(ChannelHandlerContext ctx, String msg) throws Exception { System.out.println(msg); } }SimpleChatClientInitializer.java类:
package com.mangocool.netty; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelPipeline; import io.netty.channel.socket.SocketChannel; 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; /** * Created by MANGOCOOL on 2015/10/30. */ public class SimpleChatClientInitializer extends ChannelInitializer<SocketChannel> { @Override public void initChannel(SocketChannel 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("handler", new SimpleChatClientHandler()); } }SimpleChatClient.java类:
package com.mangocool.netty; import io.netty.bootstrap.Bootstrap; import io.netty.channel.Channel; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.nio.NioSocketChannel; import java.util.Scanner; /** * Created by MANGOCOOL on 2015/10/30. */ public class SimpleChatClient { private static String host = "localhost"; private static int port = 8080; public static void main(String[] args) throws Exception { new SimpleChatClient(host, port).run(); } public SimpleChatClient(String host, int port) { this.host = host; this.port = port; } public void run() throws Exception { EventLoopGroup group = new NioEventLoopGroup(); try { Bootstrap bootstrap = new Bootstrap() .group(group) .channel(NioSocketChannel.class) .handler(new SimpleChatClientInitializer()); Channel channel = bootstrap.connect(host, port).sync().channel(); Scanner sc = new Scanner(System.in); System.out.println("please enter..."); boolean exit = false; // 输入exit,退出系统 while(!exit) { String str = sc.next(); channel.writeAndFlush(str + "\r\n"); if(str.equalsIgnoreCase("exit")) { exit = true; channel.close(); } } } catch (Exception e) { e.printStackTrace(); } finally { group.shutdownGracefully(); } } }SimpleChatServerHandler.java类:
package com.mangocool.netty; import io.netty.channel.Channel; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.SimpleChannelInboundHandler; import io.netty.channel.group.ChannelGroup; import io.netty.channel.group.DefaultChannelGroup; import io.netty.util.concurrent.GlobalEventExecutor; /** * Created by MANGOCOOL on 2015/10/30. */ public class SimpleChatServerHandler extends SimpleChannelInboundHandler<String> { public static ChannelGroup channels = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE); @Override public void handlerAdded(ChannelHandlerContext ctx) throws Exception { Channel incoming = ctx.channel(); for (Channel channel : channels) { channel.writeAndFlush("[SERVER] - " + incoming.remoteAddress() + " 加入\n"); } channels.add(ctx.channel()); } @Override public void handlerRemoved(ChannelHandlerContext ctx) throws Exception { Channel incoming = ctx.channel(); for (Channel channel : channels) { channel.writeAndFlush("[SERVER] - " + incoming.remoteAddress() + " 离开\n"); } channels.remove(ctx.channel()); } // 优先级高于messageReceived方法,有了这个方法就会屏蔽messageReceived方法 // @Override // public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { // System.out.println("channelRead"); // Channel incoming = ctx.channel(); // for (Channel channel : channels) { // if (channel != incoming){ // channel.writeAndFlush("[" + incoming.remoteAddress() + "]" + msg + "\n"); // } else { // channel.writeAndFlush("server: " + msg + "\n"); // } // } // } @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { Channel incoming = ctx.channel(); System.out.println("client "+incoming.remoteAddress()+" 在线"); } @Override public void channelInactive(ChannelHandlerContext ctx) throws Exception { Channel incoming = ctx.channel(); System.out.println("client "+incoming.remoteAddress()+" 掉线"); } @Override protected void messageReceived(ChannelHandlerContext ctx, String msg) throws Exception { Channel incoming = ctx.channel(); for (Channel channel : channels) { if (channel != incoming){ // System.out.println("[" + incoming.remoteAddress() + "] " + msg); channel.writeAndFlush("[" + incoming.remoteAddress() + "] " + msg + "\n"); } else { // System.out.println("server: " + msg); channel.writeAndFlush("server: " + msg + "\n"); } } } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { Channel incoming = ctx.channel(); System.out.println("client "+incoming.remoteAddress()+" 异常"); // 当出现异常就关闭连接 cause.printStackTrace(); ctx.close(); } }SimpleChatServerInitializer.java类:
package com.mangocool.netty; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelPipeline; import io.netty.channel.socket.SocketChannel; 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; /** * Created by MANGOCOOL on 2015/10/30. */ public class SimpleChatServerInitializer extends ChannelInitializer<SocketChannel> { @Override public void initChannel(SocketChannel 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("handler", new SimpleChatServerHandler()); System.out.println("client "+ch.remoteAddress() +" 连接上"); } }SimpleChatServer.java类:
package com.mangocool.netty; import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelOption; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.nio.NioServerSocketChannel; /** * Created by MANGOCOOL on 2015/10/30. */ public class SimpleChatServer { private static int port = 8080; public SimpleChatServer(int port) { this.port = port; } public void run() throws Exception { EventLoopGroup bossGroup = new NioEventLoopGroup(); EventLoopGroup workerGroup = new NioEventLoopGroup(); try { ServerBootstrap b = new ServerBootstrap(); b.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) .childHandler(new SimpleChatServerInitializer()) .option(ChannelOption.SO_BACKLOG, 128) .childOption(ChannelOption.SO_KEEPALIVE, true); System.out.println("server 启动了"); // 绑定端口,开始接收进来的连接 ChannelFuture f = b.bind(port).sync(); // 等待服务器 socket 关闭 。 // 在这个例子中,这不会发生,但你可以优雅地关闭你的服务器。 f.channel().closeFuture().sync(); } finally { workerGroup.shutdownGracefully(); bossGroup.shutdownGracefully(); System.out.println("server 关闭了"); } } public static void main(String[] args) throws Exception { new SimpleChatServer(port).run(); } }
到此就可以开始测试了,测试时建议开启3个client,效果更明显,以下是我的测试结果:
server端:
client01端:
client02端:
client03端:
到此例子就结束了,小伙伴们,动手试试!
还有一个叫做Grizzly的NIO开源框架,有时间也可以学习学习!
官网:https://grizzly.java.net/overview.html
参考来源:
官网:http://netty.io/wiki/user-guide-for-5.x.html
译文:http://ifeve.com/netty5-user-guide/
示例:https://github.com/netty/netty/tree/master/example/src/main/java/io/netty/example
推荐书籍:中文名:《Netty权威指南》 外文名:Netty:The Definitive Guide 作者:李林锋
他的文章:http://www.infoq.com/cn/author/%E6%9D%8E%E6%9E%97%E9%94%8B#文章
标签: Netty Java NIO Socket Demo
分享:
崇尚极简,热爱技术,喜欢唱歌,热衷旅行,爱好电子产品的一介码农。
联系QQ:58742094
联系电话:
工作邮箱:
当你的才华还撑不起你的野心的时候,你就应该静下心来学习,永不止步!
人生之旅历途甚长,所争决不在一年半月,万不可因此着急失望,招精神之萎葸。
Copyright 2015- 芒果酷(mangocool.com) All rights reserved. 湘ICP备14019394号
免责声明:本网站部分文章转载其他媒体,意在为公众提供免费服务。如有信息侵犯了您的权益,可与本网站联系,本网站将尽快予以撤除。