本人写的Netty相关文章,全部基于版本4.1.33.Final
目录
1、概述
2、入门案例
一:概述
虽然原生的java给我们提供了非常强大NIO的功能,但是由于使用上的,众多网络编程上的问题,任然需要开发者自己开发维护,因为选择Netty这种基于原生NIO进行开发的框架来助于我们的开发。
二:入门案例
学任何框架都是从入门案例,netty也不例外,先搭建一个简单的服务端,客户端来理解Netty的便捷性。
需求:客户端连接服务端后,给服务端发送一条消息,服务端收到消息后,给客户端发送一条消息
服务端:
public class NettyServer {
private int port;
public NettyServer(int port){
this.port = port;
}
public void start(){
// boss 是处理客户端连接的线程池
// worker 是处理从客户端连接转发过来的IO数据的读写线程池
NioEventLoopGroup boss = new NioEventLoopGroup();
NioEventLoopGroup worker = new NioEventLoopGroup();
try{
// ServerBootstrap 对外一个便利创建服务端,Builder建造者设计模式
ServerBootstrap sb = new ServerBootstrap();
// 绑定线程池
sb.group(boss,worker)
// 绑定channel 服务端绑定NioServerSocketChannel,此实现jdk的ServerSocketChannel
.channel(NioServerSocketChannel.class)
// 绑定服务端相关参数,可添加绑定多个参数
.option(ChannelOption.SO_BACKLOG, 1024) //指定此套接口排队的最大连接个数
// IO事件处理类,主要处理IO事件的读写
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
// 添加
pipeline.addLast(new NettyServerHandler());
}
});
// 绑定端口,同步等待成功
ChannelFuture cf = sb.bind(port).sync();
System.out.println("服务已启动.................监听端口:" + port);
// 等待服务器监听端口关闭
cf.channel().closeFuture().sync();
}catch (Exception e){
// 优雅关闭线程资源
boss.shutdownGracefully();
worker.shutdownGracefully();
}
}
public static void main(String[] args) {
NettyServer nettyServer = new NettyServer(9090);
nettyServer.start();
}
}
handler处理器:
public class NettyServerHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
ByteBuf byteBuf = (ByteBuf) msg;
byte[] buf = new byte[byteBuf.readableBytes()];
byteBuf.readBytes(buf);
String str = new String(buf, "utf-8");
System.out.println("收到信息 : " + str);
long currentTimeMillis = System.currentTimeMillis();
ByteBuf writeBuf = Unpooled.copiedBuffer(("服务端发送的消息 : " + currentTimeMillis).getBytes());
ctx.write(writeBuf);
}
@Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
/**
* 注意:此flush()方法是将消息发送队列中的消息写入到SocketChannel中发送给对方。
* 从性能角度考虑,为了防止频繁地唤醒Selector进行消息发送,Netty的write()方法并不直接将消息写入SocketChannel中,
* 调用write()方法只是把待发送的消息放到发送缓冲数组中,再通过调用flush()方法,将发送缓冲区中的消息全部写到SocketChannel中
*/
System.out.println("channelReadComplete............");
ctx.flush();
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
System.out.println("消息异常.....exceptionCaught ");
// 当发送异常时,关闭ctx,是否和ctx相关联的句柄等资源
ctx.close();
}
@Override
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
System.out.println("用户事件触发.... userEventTriggered");
super.userEventTriggered(ctx, evt);
}
}
客户端代码:
public class NettyClient {
public static void main(String[] args) throws InterruptedException {
NioEventLoopGroup group = new NioEventLoopGroup();
try{
Bootstrap b = new Bootstrap();
b.group(group).channel(NioSocketChannel.class)
.option(ChannelOption.TCP_NODELAY,true)
.handler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(new NettyClientHandler());
}
});
// 异步连接服务端
ChannelFuture f = b.connect(new InetSocketAddress(9090)).sync();
// 等待关闭
f.channel().closeFuture().sync();
}finally {
//优雅退出,是否线程池资源
group.shutdownGracefully();
}
}
}
客户端handler处理器:
public class NettyClientHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
// 当客户端与服务端链路建立成功后调用此方法
System.out.println("channelActive...");
ByteBuf message = Unpooled.copiedBuffer("fangyouyun client msg".getBytes());
ctx.writeAndFlush(message);
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
System.out.println("channelRead......");
ByteBuf returnMsg = (ByteBuf)msg;
byte[] bytes = new byte[returnMsg.readableBytes()];
returnMsg.readBytes(bytes);
System.out.println("收到服务端返回的消息 : " + new String(bytes));
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
ctx.close();
System.out.println(cause.getMessage());
}
}
测试结果:
博客中案例代码:https://download.youkuaiyun.com/download/qq_22871607/11072379