介绍
常用方法
public Server Bootstrap group(EventLoopGroup parentGroup,EventLoopGroup childGroup)
,该方法用于服务器端,用来设置两个EventLooppublic B group(EventLoop Groupgroup)
,该方法用于客户端,用来设置一个EventLooppublic B channel(Class channelClass)
,该方法用来设置一个服务器端的通道实现、public B option(ChannelOption option,Tvalue)
,用来给ServerChannel添加配置public Server Bootstrap childOption(ChannelOption childOption,T value)
,用来给接收到的通道添加配置public ServerBootstrap childHandler(ChannelHandler childHandler)
,该方法用来设置业务处理类(自定义的handler)public ChannelFuture bind(int inetPort)
,该方法用于服务器端,用来设置占用的端口号public ChannelFuture connect(String inetHost,int inetPort)
,该方法用于客户端,用来连接服务器端介绍
子类NioEventLoopGroup常用方法
public NioEventLoopGroup()
,构造方法public Future> shutdownGracefully()
,断开连接,关闭线程介绍
介绍
常用的Channel类型
介绍
一个 Channel 包含了一个 ChannelPipeline,而 ChannelPipeline 中又维护了一个由 ChannelHandlerContext 组成的双向链表,并且每个 ChannelHandlerContext 中又关联着一个 ChannelHandler
入站事件和出站事件在一个双向链表中,入站事件会从链表 head 往后传递到最后一个入站的 handler,出站事件会从链表 tail 往前传递到最前一个出站的 handler,两种类型的 handler 互不干扰
常用方法
ChannelPipeline addFirst(ChannelHandler... handlers)
,把一个业务处理类(handler)添加到链中的第一个位置ChannelPipeline addLast(ChannelHandler... handlers)
,把一个业务处理类(handler)添加到链中的最后一个位置介绍
常用方法
ChannelFuture close()
,关闭通道ChannelOutboundInvoker flush()
,刷新ChannelFuture writeAndFlush(Object msg)
, 将 数 据 写 到 ChannelPipeline 中,当 ChannelHandler 的下一个 ChannelHandler 开始处理(出站)介绍
常用子类
适配器
public class ChannelInboundHandlerAdapter extends ChannelHandlerAdapter implements ChannelInboundHandler {
public ChannelInboundHandlerAdapter() {
}
public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
ctx.fireChannelRegistered();
}
public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
ctx.fireChannelUnregistered();
}
//通道就绪事件
public void channelActive(ChannelHandlerContext ctx) throws Exception {
ctx.fireChannelActive();
}
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
ctx.fireChannelInactive();
}
//通道读取数据事件
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
ctx.fireChannelRead(msg);
}
//数据读取完毕事件
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
ctx.fireChannelReadComplete();
}
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
ctx.fireUserEventTriggered(evt);
}
public void channelWritabilityChanged(ChannelHandlerContext ctx) throws Exception {
ctx.fireChannelWritabilityChanged();
}
//通道发生异常事件
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
ctx.fireExceptionCaught(cause);
}
}
介绍
ChannelOption 参数
介绍
常用方法
Channel channel()
,返回当前正在进行IO操作的通道ChannelFuture sync()
,等待异步操作执行完毕介绍
Unpooled常用方法
public static ByteBuf copiedBuffer(CharSequence string, Charset charset)
,通过给定的数据和字符编码返回一个 ByteBuf 对象(类似于 NIO 中的 ByteBuffer 但有区别)public static ByteBuf buffer(int initialCapacity)
,开辟initialCapacity大小的bytebufferByteBfu和ByteBuffer比较
案例
public static void main(String[] args) {
//创建一个ByteBuf
ByteBuf buffer = Unpooled.buffer(10);
for(int i = 0; i < 10; i++) {
buffer.writeByte(i);
}
System.out.println("capacity=" + buffer.capacity());//10
for(int i = 0; i < buffer.capacity(); i++) {
//System.out.println(buffer.getByte(i));
//readByte会自动使readIndex后移
System.out.println(buffer.readByte());
}
}
public static void main(String[] args) {
//创建ByteBuf
ByteBuf byteBuf = Unpooled.copiedBuffer("hello,world!", Charset.forName("utf-8"));
//属性
System.out.println(byteBuf.arrayOffset()); // 0
System.out.println(byteBuf.readerIndex()); // 0
System.out.println(byteBuf.writerIndex()); // 12
System.out.println(byteBuf.capacity()); // 36
//System.out.println(byteBuf.readByte()); //
System.out.println(byteBuf.getByte(0)); // 104
int len = byteBuf.readableBytes(); //可读的字节数 12
System.out.println("len=" + len);
//使用for取出各个字节
for(int i = 0; i < len; i++) {
System.out.println((char) byteBuf.getByte(i));
}
//按照某个范围读取
System.out.println(byteBuf.getCharSequence(0, 4, Charset.forName("utf-8")));
System.out.println(byteBuf.getCharSequence(4, 6, Charset.forName("utf-8")));
//转为byte[]
if(byteBuf.hasArray()) { // true
byte[] content = byteBuf.array();
//将 content 转成字符串
System.out.println(new String(content, Charset.forName("utf-8")));
System.out.println("byteBuf=" + byteBuf);
}
}
添加方法
在ChannelPipeline里加入一个netty 提供 IdleStateHandler
//IdleStateHandler 是netty 提供的处理空闲状态的处理器
public IdleStateHandler(
long readerIdleTime, //表示多长时间没有读, 就会发送一个心跳检测包检测是否连接
long writerIdleTime, long allIdleTime, //表示多长时间没有写, 就会发送一个心跳检测包检测是否连接
TimeUnit unit //表示多长时间没有读写, 就会发送一个心跳检测包检测是否连接
)
当 IdleStateEvent 触发后 , 就会传递给管道 的下一个handler去处理,通过调用(触发)下一个handler 的 userEventTiggered , 在该方法中去处理 IdleStateEvent(读空闲,写空闲,读写空闲)
案例
HeartbeatServerHandler
public class HeartbeatServerHandler extends ChannelInboundHandlerAdapter {
/**
*
* @param ctx 上下文
* @param evt 事件
* @throws Exception
*/
@Override
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
if(evt instanceof IdleStateEvent) {
//将 evt 向下转型 IdleStateEvent
IdleStateEvent event = (IdleStateEvent) evt;
String eventType = null;
switch (event.state()) {
case READER_IDLE:
eventType = "读空闲";
break;
case WRITER_IDLE:
eventType = "写空闲";
break;
case ALL_IDLE:
eventType = "读写空闲";
break;
}
System.out.println(ctx.channel().remoteAddress() + "--超时时间--" + eventType);
System.out.println("服务器做相应处理..");
//如果发生空闲,我们关闭通道
// ctx.channel().close();
}
}
}
YzxServer
public class YzxServer {
public static void main(String[] args) throws Exception{
//创建两个线程组
EventLoopGroup bossGroup = new NioEventLoopGroup(1);
EventLoopGroup workerGroup = new NioEventLoopGroup(); //8个NioEventLoop
try {
ServerBootstrap serverBootstrap = new ServerBootstrap();
serverBootstrap.group(bossGroup, workerGroup);
serverBootstrap.channel(NioServerSocketChannel.class);
serverBootstrap.handler(new LoggingHandler(LogLevel.INFO));
serverBootstrap.childHandler(new ChannelInitializer() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
//TODO 加入其他handler
//加入IdleStateHandler
pipeline.addLast(new IdleStateHandler(7000,7000,10, TimeUnit.SECONDS));
//加入一个对IdleStateHandler进一步处理的handler(自定义)
pipeline.addLast(new HeartbeatServerHandler());
}
});
//启动服务器
ChannelFuture channelFuture = serverBootstrap.bind(7000).sync();
channelFuture.channel().closeFuture().sync();
}finally {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
}