Java中的NIO是一种解决阻塞式IO问题的基本技术,但是NIO的编写对java程序员是有比较高的要求的。那么Netty就是一种简化操作的一个成熟的网络IO编程框架。这里简单介绍一个程序,代码是《netty in action》里面的,不过那个里面的实例有点问题,反正我没有跑成功,修改后成功。直接上代码:
一、服务器编写
Server代码,监听连接
1 package com.gerry.netty.server;
2
3 import io.netty.bootstrap.ServerBootstrap;
4 import io.netty.channel.ChannelFuture;
5 import io.netty.channel.ChannelInitializer;
6 import io.netty.channel.EventLoopGroup;
7 import io.netty.channel.nio.NioEventLoopGroup;
8 import io.netty.channel.socket.SocketChannel;
9 import io.netty.channel.socket.nio.NioServerSocketChannel;
10
11 public class EchoServer {
12 private final int port;
13
14 public EchoServer(int port) {
15 this.port = port;
16 }
17
18 public void start() throws Exception {
19 EventLoopGroup group = new NioEventLoopGroup();
20 try {
21 ServerBootstrap sb = new ServerBootstrap();
22 sb.group(group) // 绑定线程池
23 .channel(NioServerSocketChannel.class) // 指定使用的channel
24 .localAddress(this.port)// 绑定监听端口
25 .childHandler(new ChannelInitializer<SocketChannel>() { // 绑定客户端连接时候触发操作
26
27 @Override
28 protected void initChannel(SocketChannel ch) throws Exception {
29 System.out.println("connected...; Client:" + ch.remoteAddress());
30 ch.pipeline().addLast(new EchoServerHandler()); // 客户端触发操作
31 }
32 });
33 ChannelFuture cf = sb.bind().sync(); // 服务器异步创建绑定
34 System.out.println(EchoServer.class + " started and listen on " + cf.channel().localAddress());
35 cf.channel().closeFuture().sync(); // 关闭服务器通道
36 } finally {
37 group.shutdownGracefully().sync(); // 释放线程池资源
38 }
39 }
40
41 public static void main(String[] args) throws Exception {
42 new EchoServer(65535).start(); // 启动
43 }
44 }
具体的处理客户端连接的代码
1 package com.gerry.netty.server;
2
3 import io.netty.buffer.Unpooled;
4 import io.netty.channel.ChannelFutureListener;
5 import io.netty.channel.ChannelHandlerContext;
6 import io.netty.channel.ChannelInboundHandlerAdapter;
7
8 public class EchoServerHandler extends ChannelInboundHandlerAdapter {
9 @Override
10 public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
11 System.out.println("server channelRead...; received:" + msg);
12 ctx.write(msg);
13 }
14
15 @Override
16 public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
17 System.out.println("server channelReadComplete..");
18 // 第一种方法:写一个空的buf,并刷新写出区域。完成后关闭sock channel连接。
19 ctx.writeAndFlush(Unpooled.EMPTY_BUFFER).addListener(ChannelFutureListener.CLOSE);
20 //ctx.flush(); // 第二种方法:在client端关闭channel连接,这样的话,会触发两次channelReadComplete方法。
21 //ctx.flush().close().sync(); // 第三种:改成这种写法也可以,但是这中写法,没有第一种方法的好。
22 }
23
24 @Override
25 public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
26 System.out.println("server occur exception:" + cause.getMessage());
27 cause.printStackTrace();
28 ctx.close(); // 关闭发生异常的连接
29 }
30 }
二、客户端编写
具体的连接代码
1 package com.gerry.netty.client;
2
3 import io.netty.bootstrap.Bootstrap;
4 import io.netty.channel.ChannelFuture;
5 import io.netty.channel.ChannelInitializer;
6 import io.netty.channel.EventLoopGroup;
7 import io.netty.channel.nio.NioEventLoopGroup;
8 import io.netty.channel.socket.SocketChannel;
9 import io.netty.channel.socket.nio.NioSocketChannel;
10
11 import java.net.InetSocketAddress;
12
13 public class EchoClient {
14 private final String host;
15 private final int port;
16
17 public EchoClient() {
18 this(0);
19 }
20
21 public EchoClient(int port) {
22 this("localhost", port);
23 }
24
25 public EchoClient(String host, int port) {
26 this.host = host;
27 this.port = port;
28 }
29
30 public void start() throws Exception {
31 EventLoopGroup group = new NioEventLoopGroup();
32 try {
33 Bootstrap b = new Bootstrap();
34 b.group(group) // 注册线程池
35 .channel(NioSocketChannel.class) // 使用NioSocketChannel来作为连接用的channel类
36 .remoteAddress(new InetSocketAddress(this.host, this.port)) // 绑定连接端口和host信息
37 .handler(new ChannelInitializer<SocketChannel>() { // 绑定连接初始化器
38 @Override
39 protected void initChannel(SocketChannel ch) throws Exception {
40 System.out.println("connected...");
41 ch.pipeline().addLast(new EchoClientHandler());
42 }
43 });
44 System.out.println("created..");
45
46 ChannelFuture cf = b.connect().sync(); // 异步连接服务器
47 System.out.println("connected..."); // 连接完成
48
49 cf.channel().closeFuture().sync(); // 异步等待关闭连接channel
50 System.out.println("closed.."); // 关闭完成
51 } finally {
52 group.shutdownGracefully().sync(); // 释放线程池资源
53 }
54 }
55
56 public static void main(String[] args) throws Exception {
57 new EchoClient("127.0.0.1", 65535).start(); // 连接127.0.0.1/65535,并启动
58 }
59 }
连接成功后,具体的通信代码
1 package com.gerry.netty.client;
2
3 import java.nio.charset.Charset;
4
5 import io.netty.buffer.ByteBuf;
6 import io.netty.buffer.ByteBufUtil;
7 import io.netty.buffer.Unpooled;
8 import io.netty.channel.ChannelHandlerContext;
9 import io.netty.channel.SimpleChannelInboundHandler;
10 import io.netty.util.CharsetUtil;
11
12 public class EchoClientHandler extends SimpleChannelInboundHandler<ByteBuf> {
13
14 @Override
15 public void channelActive(ChannelHandlerContext ctx) throws Exception {
16 System.out.println("client channelActive..");
17 ctx.writeAndFlush(Unpooled.copiedBuffer("Netty rocks!", CharsetUtil.UTF_8)); // 必须有flush
18
19 // 必须存在flush
20 // ctx.write(Unpooled.copiedBuffer("Netty rocks!", CharsetUtil.UTF_8));
21 // ctx.flush();
22 }
23
24 @Override
25 protected void channelRead0(ChannelHandlerContext ctx, ByteBuf msg) throws Exception {
26 System.out.println("client channelRead..");
27 ByteBuf buf = msg.readBytes(msg.readableBytes());
28 System.out.println("Client received:" + ByteBufUtil.hexDump(buf) + "; The value is:" + buf.toString(Charset.forName("utf-8")));
29 //ctx.channel().close().sync();// client关闭channel连接
30 }
31
32 @Override
33 public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
34 cause.printStackTrace();
35 ctx.close();
36 }
37
38 }
三、结果
先运行server,在运行client即可。


转载链接:http://www.cnblogs.com/liuming1992/p/4758532.html
以上netty使用的版本
<!-- https://mvnrepository.com/artifact/io.netty/netty-all -->
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.6.Final</version>
</dependency>
