换了公司,这家公司的第一项目就是接受别人原来的netty项目,真是重来没有搞过java 网络编程,搞过也是原来写android时候搞过,这次这么吊的东西还是第一次玩。
不得不说还是要好好学习java基础,我就是基础太差了,感觉和那位之前的同志写的代码还是有很多差距。电子科技大学是个好学校。
netty 异步非阻塞式网络框架
参考教程 netty实战
ChannelHandler用来定义处理入站事件的方法,一般用来编写核心处理逻辑
一般复写四个方法
- channelRead() - 每个信息入站都会调用
- channelReadComplete() - 通知处理器最后的channelread() 是当前批处理中的最后一条消息时调用
- exceptionCaught()- 读操作时捕获到异常时调用
关键:
1.ChannelHandler是给不同类型的事件调用
2.应用程序实现或扩展ChannelHanler挂接到事件生命周期和提供自定义应用逻辑。
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandler.Sharable;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
@Sharable //标识这是一个这个类的实例可以在channel中共享
public class EchoServerHandler extends ChannelInboundHandlerAdapter{
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
super.channelActive(ctx);
System.out.println("echoServerhandler---------->激活");
}
//重channel中读取 这里的ChannelHandkerContext 就是在bootstrap中定义的那个Channel
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
ByteBuf in = (ByteBuf)msg;
System.out.println("server received:"+in.toString());
ctx.write(in);//写入channel 然后将这些信息返回给发送者
}
//重channel读取完毕
@Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
//将所有的待审的消息发送,然后冲刷 并且关闭通道 后面那个监听 只是监听通道是否关闭
ctx.writeAndFlush(Unpooled.EMPTY_BUFFER).addListener(ChannelFutureListener.CLOSE);
}
//通道连接出现异常
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
cause.printStackTrace();
ctx.close();
}
}
编写引导服务器Server
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandler.Sharable;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
@Sharable //标识这是一个这个类的实例可以在channel中共享
public class EchoServerHandler extends ChannelInboundHandlerAdapter{
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
super.channelActive(ctx);
System.out.println("echoServerhandler---------->激活");
}
//重channel中读取
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
ByteBuf in = (ByteBuf)msg;
System.out.println("server received:"+in.toString());
ctx.write(in);//写入channel 然后将这些信息返回给发送者
}
//重channel读取完毕
@Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
//将所有的待审的消息发送,然后冲刷 并且关闭通道 后面那个监听 只是监听通道是否关闭
ctx.writeAndFlush(Unpooled.EMPTY_BUFFER).addListener(ChannelFutureListener.CLOSE);
}
//通道连接出现异常
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
cause.printStackTrace();
ctx.close();
}
}
netty启动代码
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new ServerInitializer())
.option(ChannelOption.SO_BACKLOG, 1024)
.childOption(ChannelOption.TCP_NODELAY, true)
.handler(new LoggingHandler(LogLevel.INFO));
ChannelFuture f = b.bind(port).sync();
f.channel().closeFuture().sync();
} catch (InterruptedException e) {
LOGGER.error("nio start error");
} finally {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
上面的代码用于创建一个简单的netty server
netty程序的基本模块
Bootstrtrap(引导)
用于应用程序网络层配置的容器
Channel
Channel定义了与socket丰富交互的操作集,bind,close,config,connect,isActive,read,write等等,常用的Channel有,LocalServerChannel,NioSocketChannel等,也就是说netty中对socket的一些操作是在Channel中定义的
ChannelHander
支持很多协议,平且提供用于数据处理的容器,在netty的服务器中他承担主要的对核心业务网的承载
常用的接口是ChannelInboundHandler,业务逻辑经常存在与一个或多个ChannelInboundHanler中
ChannelPipeline
protected void initChannel(SocketChannel ch) throws Exception {
// TODO Auto-generated method stub
ch.pipeline().addLast(new HttpResponseEncoder());
ch.pipeline().addLast(new HttpRequestDecoder());
ch.pipeline().addLast(new HttpServerInboundHandler());
}
ChannelPipeline提供了一个容器给ChannelHandler链并提供了一个API用于管理沿着链入站和出站事件的流动。每个Channel都有一个自己的ChannelPipeline,也就是说ChannelPipeline是存在与Channel中的
EventLoop
EventLoop用于处理Channel的I/O操作,一个单一的EventLoop通常会处理多个Channel事件,一个EventLoopGroup可以包含多个EventLoop和提供一种迭代用于检索清单中的下一个
ChannelFuture
Netty所有的I/O操作都是异步的,因为一个操作可能无法立即返回,我们需要一种方法在以后确认他的结果。处于这个目的,Netty提供了接口ChannelFuture,他的addListener方法注册一个ChannelFutureListener,操作完成时,可以被通知(无论成功与否)
Transport API
每个Channel都会分配一个ChannelPipeline和ChannelConfig。ChannelConfig负责设置并存储Channel的配置,并允许在允许期间更新他们。
ChannelPipeline容纳了使用的ChannelHandler实例,这些ChannelHanler将处理通道传递的“入站”和出站数据以及时间,ChannelHandler的实现允许你改变数据状态和传
输数据
socketChannel.pipeline().addLast(new ServerHandler());
你还可以在运行时根据需要添加 ChannelHandler 实例到ChannelPipeline 或从 ChannelPipeline 中删除,这能帮助我们构建高度灵活的 Netty 程序。例如,你可以支持 STARTTLS 协议,只需通过加入适当的 ChannelHandler(这里是 SslHandler)到的ChannelPipeline 中,当被请求这个协议时。
Channel是线程安全的