Netty学习:搭建一个简单的Netty服务
Netty 是一个基于 JAVA NIO 类库的异步通信框架,它的架构特点是:异步非阻塞、基于事件驱动、高性能、高可靠性和高可定制性。换句话说,Netty是一个NIO框架,使用它可以简单快速地开发网络应用程序,比如客户端和服务端的协议。Netty大大简化了网络程序的开发过程比如TCP和UDP的 Socket的开发。Netty 已逐渐成为 Java NIO 编程的首选框架。
项目官方地址:http://netty.io/index.html
一. Netty 的优点:
-
API 使用简单,开发门槛低;
-
功能强大,预置了多种编解码功能,支持多种主流协议;
-
定制能力强,可以通过 ChannelHandler 对通信框架进行灵活的扩展;
-
性能高,通过与其它业界主流的 NIO 框架对比,Netty 的综合性能最优;
-
社区活跃,版本迭代周期短,发现的 BUG 可以被及时修复,同时,更多的新功能会被加入;
-
经历了大规模的商业应用考验,质量得到验证。在互联网、大数据、网络游戏、企业应用、电信软件等众多行业得到成功商用,证明了它完全满足不同行业的商用标准。
二. 搭建Netty服务:
-
添加pom依赖
Pom代码
-
<dependency>
-
<groupId>io.netty</groupId>
-
<artifactId>netty-all</artifactId>
-
<version>4.1.0.Final</version>
-
</dependency>
-
-
SimpleServer(服务端)
Java代码
-
package com.yingjun.netty.server;
-
-
import io.netty.bootstrap.ServerBootstrap;
-
import io.netty.channel.ChannelFuture;
-
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;
-
-
/**
-
*
-
* Netty中,通讯的双方建立连接后,会把数据按照ByteBuf的方式进行传输,
-
* 例如http协议中,就是通过HttpRequestDecoder对ByteBuf数据流进行处理,转换成http的对象。
-
*
-
*/
-
public class SimpleServer {
-
private int port;
-
-
public SimpleServer(int port) {
-
this.port = port;
-
}
-
-
public void run() throws Exception {
-
//EventLoopGroup是用来处理IO操作的多线程事件循环器
-
//bossGroup 用来接收进来的连接
-
EventLoopGroup bossGroup = new NioEventLoopGroup();
-
//workerGroup 用来处理已经被接收的连接
-
EventLoopGroup workerGroup = new NioEventLoopGroup();
-
try {
-
//启动 NIO 服务的辅助启动类
-
ServerBootstrap b = new ServerBootstrap();
-
b.group(bossGroup, workerGroup)
-
//配置 Channel
-
.channel(NioServerSocketChannel.class)
-
.childHandler(new ChannelInitializer<SocketChannel>() {
-
@Override
-
public void initChannel(SocketChannel ch) throws Exception {
-
// 注册handler
-
ch.pipeline().addLast(new SimpleServerHandler());
-
}
-
})
-
.option(ChannelOption.SO_BACKLOG, 128)
-
.childOption(ChannelOption.SO_KEEPALIVE, true);
-
-
// 绑定端口,开始接收进来的连接
-
ChannelFuture f = b.bind(port).sync();
-
// 等待服务器 socket 关闭 。
-
f.channel().closeFuture().sync();
-
} finally {
-
workerGroup.shutdownGracefully();
-
bossGroup.shutdownGracefully();
-
}
-
}
-
-
public static void main(String[] args) throws Exception {
-
new SimpleServer(9999).run();
-
}
-
}
-
-
SimpleServerHandler(服务端请求处理Handler)
Java代码
-
package com.yingjun.netty.server;
-
-
import io.netty.buffer.ByteBuf;
-
import io.netty.channel.ChannelHandlerContext;
-
import io.netty.channel.ChannelInboundHandlerAdapter;
-
-
public class SimpleServerHandler extends ChannelInboundHandlerAdapter {
-
-
@Override
-
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
-
System.out.println("SimpleServerHandler.channelRead");
-
ByteBuf result = (ByteBuf) msg;
-
byte[] result1 = new byte[result.readableBytes()];
-
// msg中存储的是ByteBuf类型的数据,把数据读取到byte[]中
-
result.readBytes(result1);
-
String resultStr = new String(result1);
-
// 接收并打印客户端的信息
-
System.out.println("Client said:" + resultStr);
-
// 释放资源,这行很关键
-
result.release();
-
-
// 向客户端发送消息
-
String response = "hello client!";
-
// 在当前场景下,发送的数据必须转换成ByteBuf数组
-
ByteBuf encoded = ctx.alloc().buffer(4 * response.length());
-
encoded.writeBytes(response.getBytes());
-
ctx.write(encoded);
-
ctx.flush();
-
}
-
-
@Override
-
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
-
// 当出现异常就关闭连接
-
cause.printStackTrace();
-
ctx.close();
-
}
-
-
@Override
-
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
-
ctx.flush();
-
}
-
-
}
-
-
SimpleServer(客户端)
Java代码
-
package com.yingjun.netty.server;
-
-
import io.netty.bootstrap.Bootstrap;
-
import io.netty.bootstrap.ServerBootstrap;
-
import io.netty.channel.ChannelFuture;
-
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.channel.socket.nio.NioSocketChannel;
-
-
public class SimpleClient {
-
-
public void connect(String host, int port) throws Exception {
-
EventLoopGroup workerGroup = new NioEventLoopGroup();
-
-
try {
-
Bootstrap b = new Bootstrap();
-
b.group(workerGroup);
-
b.channel(NioSocketChannel.class);
-
b.option(ChannelOption.SO_KEEPALIVE, true);
-
b.handler(new ChannelInitializer<SocketChannel>() {
-
@Override
-
public void initChannel(SocketChannel ch) throws Exception {
-
ch.pipeline().addLast(new SimpleClientHandler());
-
}
-
});
-
-
// Start the client.
-
ChannelFuture f = b.connect(host, port).sync();
-
-
// Wait until the connection is closed.
-
f.channel().closeFuture().sync();
-
} finally {
-
workerGroup.shutdownGracefully();
-
}
-
}
-
-
public static void main(String[] args) throws Exception {
-
SimpleClient client=new SimpleClient();
-
client.connect("127.0.0.1", 9999);
-
}
-
-
}
-
-
SimpleServerHandler(客户端请求处理Handler springmvc+mybatis+spring 整合 下载地址 )
Java代码
-
package com.yingjun.netty.server;
-
-
import io.netty.buffer.ByteBuf;
-
import io.netty.channel.ChannelHandlerContext;
-
import io.netty.channel.ChannelInboundHandlerAdapter;
-
-
public class SimpleClientHandler extends ChannelInboundHandlerAdapter {
-
-
@Override
-
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
-
System.out.println("SimpleClientHandler.channelRead");
-
ByteBuf result = (ByteBuf) msg;
-
byte[] result1 = new byte[result.readableBytes()];
-
result.readBytes(result1);
-
System.out.println("Server said:" + new String(result1));
-
result.release();
-
}
-
-
@Override
-
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
-
// 当出现异常就关闭连接
-
cause.printStackTrace();
-
ctx.close();
-
}
-
-
-
// 连接成功后,向server发送消息
-
@Override
-
public void channelActive(ChannelHandlerContext ctx) throws Exception {
-
String msg = "hello Server!";
-
ByteBuf encoded = ctx.alloc().buffer(4 * msg.length());
-
encoded.writeBytes(msg.getBytes());
-
ctx.write(encoded);
-
ctx.flush();
-
}
-
}
-
-
运行结果:
Java代码
-
SimpleClientHandler.channelRead
-
Server said:hello client!
-
------------------------------------------
-
SimpleServerHandler.channelRead
-
Client said:hello Server!
-
SimpleServerHandler.channelRead
-
Client said:hello Server!
-