AIO案例

1,ChannelAdapter.java

package com.forezp.util.io.aio;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousServerSocketChannel;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.channels.CompletionHandler;
import java.nio.charset.Charset;
import java.util.concurrent.TimeUnit;

/***
 * aio消息处理器
 * CompletionHandler事件处理类(回调函数)
 */
public abstract class ChannelAdapter implements CompletionHandler<Integer,Object> {

    private AsynchronousSocketChannel channel;
    private Charset charset;


    public ChannelAdapter( AsynchronousSocketChannel channel,Charset charset) {
        this.charset = charset;
        this.channel = channel;
        if(channel.isOpen()){
            channelActive(new ChannelHandler(channel, charset));
        }

    }

    /***
     * 在操作完成时调用,result是操作完成返回的结果,
     * attachment是注册该回调函数时添加的附件,在回调函数调用时又会传递回来
     * @param result
     * @param attachment
     */
    public void completed(Integer result, Object attachment){

        try {
            final ByteBuffer buffer=ByteBuffer.allocate(1024);
            final long timeout=60*60l;
            channel.read(buffer, timeout, TimeUnit.SECONDS, null, new CompletionHandler<Integer, Object>() {

                @Override
                public void completed(Integer result, Object attachment) {
                    if (result == -1) {
                        try {
                            channelInactive(new ChannelHandler(channel, charset));
                            channel.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                        return;
                    }
                    buffer.flip();
                    channelRead(new ChannelHandler(channel, charset), charset.decode(buffer));
                    buffer.clear();
                    channel.read(buffer, timeout, TimeUnit.SECONDS, null, this);
                }

                @Override
                public void failed(Throwable exc, Object attachment) {
                        exc.printStackTrace();
                }
            });
        }catch (Exception e){
            e.printStackTrace();
        }



    }

    /***
     * 当操作失败时调用,Throwable是操作失败发生的异常对象,
     * attachment是注册该回调函数时添加的附件,在回调函数调用时又会传递回来
     * @param exc
     * @param attachment
     */
    public void failed(Throwable exc, Object attachment){
        exc.getStackTrace();
    }


    /***
     * 处理连接
     * @param ctx
     */
    public abstract void channelActive(ChannelHandler ctx);


    public abstract void channelInactive(ChannelHandler ctx);

    // 读取消息抽象类
    public abstract void channelRead(ChannelHandler ctx, Object msg);

}

2,AioServiceHandler.java

package com.forezp.util.io.aio.service;

import com.forezp.util.io.aio.ChannelAdapter;
import com.forezp.util.io.aio.ChannelHandler;

import java.io.IOException;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.charset.Charset;

public class AioServiceHandler extends ChannelAdapter {


    public AioServiceHandler(AsynchronousSocketChannel channel, Charset charset) {
        super(channel, charset);
    }

    @Override
    public void channelActive(ChannelHandler ctx) {
        try {
            System.out.println("已连接的IP:"+ctx.channel().getLocalAddress());
            ctx.writeAndFlush("服务端连接建立成功!"+ctx.channel().getLocalAddress());
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    @Override
    public void channelInactive(ChannelHandler ctx) {

    }

    @Override
    public void channelRead(ChannelHandler ctx, Object msg) {
        System.out.println("接收到客户端消息:"+msg);
        ctx.writeAndFlush("服务端信息处理成功!消息内容:"+msg);

    }
}

3,ChannelInitializer.java

package com.forezp.util.io.aio;

import com.forezp.util.io.aio.service.AioServer;
import com.forezp.util.io.aio.service.AioServerChannelInitializer;

import java.nio.channels.AsynchronousServerSocketChannel;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.channels.CompletionHandler;

/***
 *当I/O操作成功完成时,将调用completed方法。
 * 如果I/O操作失败,将调用failed方法
 */
public abstract class ChannelInitializer  implements CompletionHandler<AsynchronousSocketChannel, AioServer> {


  public  void completed( AsynchronousSocketChannel result, AioServer attachment){
        try {
            initChannel(result);
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            //重新接收
            attachment.serverSocketChannel().accept(attachment,this);
        }
  }

  public   void failed(Throwable exc, AioServer attachment){
      exc.getStackTrace();
  }

    /***
     * 初始化
     * @param channel
     * @return
     * @throws Exception
     */
  protected abstract void initChannel(AsynchronousSocketChannel channel) throws  Exception;

}

4,AioServer.java

package com.forezp.util.io.aio.service;

import java.net.InetSocketAddress;
import java.nio.channels.AsynchronousChannelGroup;

import java.nio.channels.AsynchronousServerSocketChannel;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executors;

public class AioServer extends Thread{

    private AsynchronousServerSocketChannel channel;

    @Override
    public void run() {
        try {
            //利用工厂方法产生一个异步通道
            channel = AsynchronousServerSocketChannel.open(
                    AsynchronousChannelGroup.withCachedThreadPool(Executors.newCachedThreadPool(),10));
            channel.bind(new InetSocketAddress(6000));
            System.out.println("服务端启动成功!....");
            CountDownLatch count=new CountDownLatch(1);
            //注册事件和事件完成后的处理器,这个CompletionHandler就是事件完成后的处理器
            channel.accept(this,new AioServerChannelInitializer());
            count.await();
        }catch (Exception e){
            e.printStackTrace();
        }

    }
    public AsynchronousServerSocketChannel serverSocketChannel(){
        return channel;
    }
    public static void main(String[] args) {
        new AioServer().start();
    }
}

 5,AioServiceHandler.java

package com.forezp.util.io.aio.service;

import com.forezp.util.io.aio.ChannelAdapter;
import com.forezp.util.io.aio.ChannelHandler;

import java.io.IOException;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.charset.Charset;

public class AioServiceHandler extends ChannelAdapter {


    public AioServiceHandler(AsynchronousSocketChannel channel, Charset charset) {
        super(channel, charset);
    }

    @Override
    public void channelActive(ChannelHandler ctx) {
        try {
            System.out.println("已连接的IP:"+ctx.channel().getLocalAddress());
            ctx.writeAndFlush("服务端连接建立成功!"+ctx.channel().getLocalAddress());
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    @Override
    public void channelInactive(ChannelHandler ctx) {

    }

    @Override
    public void channelRead(ChannelHandler ctx, Object msg) {
        System.out.println("接收到客户端消息:"+msg);
        ctx.writeAndFlush("服务端信息处理成功!消息内容:"+msg);

    }
}

6,AioServerChannelInitializer.java

package com.forezp.util.io.aio.service;

import com.forezp.util.io.aio.ChannelInitializer;

import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.charset.Charset;
import java.util.concurrent.TimeUnit;

public class AioServerChannelInitializer extends ChannelInitializer {
    @Override
    protected void initChannel(AsynchronousSocketChannel channel) throws Exception {
        channel.read(ByteBuffer.allocate(1024),10, TimeUnit.SECONDS,null,new AioServiceHandler(channel, Charset.forName("utf-8")));
    }
}

7,客服端AioClient.java

package com.forezp.util.io.aio.client;



import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.charset.Charset;
import java.util.concurrent.Future;

public class AioClient {
    public static void main(String[] args) throws Exception{

        AsynchronousSocketChannel channel= AsynchronousSocketChannel.open();
        Future<Void> future=channel.connect(new InetSocketAddress("127.0.0.1",6000));
        System.out.println("aio client start....");
        future.get();
        channel.read(ByteBuffer.allocate(1024),null,new AioClientHandler(channel, Charset.forName("utf-8")));
        Thread.sleep(1000000);
    }
}

8,AioClientHandler.java

package com.forezp.util.io.aio.client;

import com.forezp.util.io.aio.ChannelAdapter;
import com.forezp.util.io.aio.ChannelHandler;

import java.io.IOException;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.charset.Charset;

public class AioClientHandler extends ChannelAdapter {
    public AioClientHandler(AsynchronousSocketChannel channel, Charset charset) {
        super(channel, charset);
    }

    @Override
    public void channelActive(ChannelHandler ctx) {
        try {
            System.out.println("客户端连接成功!"+ ctx.channel().getLocalAddress());
        } catch (IOException e) {
            e.printStackTrace();
        }


    }

    @Override
    public void channelInactive(ChannelHandler ctx) {

    }

    @Override
    public void channelRead(ChannelHandler ctx, Object msg) {
        System.out.println("客户端接收消息:"+msg);
        ctx.writeAndFlush("客户端接收消息成功!消息内容:"+msg);

    }
}

测试,启动服务端,客户端:

 

netty框架学习之基础

 

posted on 2022-10-09 11:24  让代码飞  阅读(74)  评论(0)    收藏  举报

导航

一款免费在线思维导图工具推荐:https://www.processon.com/i/593e9a29e4b0898669edaf7f?full_name=python