重温java知识(四十、网络编程之六:AIO之一:通信模型)

JDK7开始提供AIO模型。与NIO不同的是,AIO当前的I/O操作是由操作系统进行I/O操作,而应用程序只是调用给定的类库实现读或写的操作调用。例如:当有数据流可以读取或写入时,会由操作系统将可操作的流传入read()或write()方法的缓冲区并发出操作通知,整个操作完全是异步处理实现的。

在进行异步操作时通过CompletionHandler获取异步执行结果,在Echo案例中数据读取或数据写入都可以编写一个CompletionHandler作为回调操作实现。

1-1、定义服务器端:

package com.mydemo;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousServerSocketChannel;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.channels.CompletionHandler;
import java.util.concurrent.CountDownLatch;

public class AIOServer {

    public static void main(String[] args) throws IOException {

        // 启动服务器
        new Thread(new AIOServerThread()).start();
    }

}

// 实现回调处理
class EchoHandler implements CompletionHandler<Integer, ByteBuffer> {

    // 客户端对象
    private AsynchronousSocketChannel asynchronousSocketChannel_Client;

    // 结束标记
    private boolean exit = false;

    public EchoHandler(AsynchronousSocketChannel asynchronousSocketChannel_Client) {
        this.asynchronousSocketChannel_Client = asynchronousSocketChannel_Client;
    }

    /**
     * 回调任务
     *
     * @param result
     * @param byteBuffer
     */
    @Override
    public void completed(Integer result, ByteBuffer byteBuffer) {

        // 重置缓冲区
        byteBuffer.flip();

        // 接收读取数据
        String readMessage = new String(byteBuffer.array(), 0, byteBuffer.remaining()).trim();

        // 信息提示
        System.err.println("【服务器端读取到数据】" + readMessage);

        // 回应内容
        String resultMessage = "【ECHO】" + readMessage;

        // 退出标记
        if ("exit".equalsIgnoreCase(readMessage)) {
            // 回应内容
            readMessage = "【EXIT】再见~~~~~~";
//            System.err.println(readMessage);
            this.exit = true;
        }

        // 消息回应
        this.echoWrite(readMessage);
    }

    /**
     * 异步处理失败
     *
     * @param exc
     * @param byteBuffer
     */
    @Override
    public void failed(Throwable exc, ByteBuffer byteBuffer) {
        // 关闭连接
        this.closeClient();
    }

    /**
     * 关闭客户端
     */
    private void closeClient() {
        System.out.println("客户端连接有错误,中断与此客户端的处理");
        try {
            // 通道关闭
            this.asynchronousSocketChannel_Client.close();
        } catch (Exception e) {
        }
    }

    /**
     * 数据响应
     *
     * @param readMessage
     */
    private void echoWrite(String readMessage) {

        // 开辟缓冲区
        ByteBuffer byteBuffer = ByteBuffer.allocate(100);

        // 回应处理
        byteBuffer.put(readMessage.getBytes());

        // 重置缓冲区
        byteBuffer.flip();

        // 输出
        this.asynchronousSocketChannel_Client.write(byteBuffer, byteBuffer,
                new CompletionHandler<Integer, ByteBuffer>() {
                    @Override
                    public void completed(Integer result, ByteBuffer attachment) {
                        // 有数据
                        if (attachment.hasRemaining()) {
                            // 输出
                            EchoHandler.this.asynchronousSocketChannel_Client.write(
                                    attachment,
                                    attachment,
                                    this
                            );
                        } else {
                            // 继续下一次操作
                            if (EchoHandler.this.exit = false) {
                                ByteBuffer byteBuffer_Read = ByteBuffer.allocate(100);
                                EchoHandler.this.asynchronousSocketChannel_Client.read(
                                        byteBuffer_Read,
                                        byteBuffer_Read,
                                        new EchoHandler(EchoHandler.this.asynchronousSocketChannel_Client)
                                );
                            }
                        }
                    }

                    @Override
                    public void failed(Throwable exc, ByteBuffer attachment) {
                        // 关闭通道
                        EchoHandler.this.closeClient();
                    }
                }
        );
    }
}

// 连接处理
class AcceptHandler implements CompletionHandler<AsynchronousSocketChannel, AIOServerThread> {

    @Override
    public void completed(AsynchronousSocketChannel asynchronousSocketChannel, AIOServerThread aioServerThread) {
        // 接收连接
        aioServerThread.getAsynchronousServerSocketChannel().accept(aioServerThread, this);

        // 接收缓冲区
        ByteBuffer byteBuffer = ByteBuffer.allocate(100);

        // 交由其他异步处理
        asynchronousSocketChannel.read(byteBuffer, byteBuffer, new EchoHandler(asynchronousSocketChannel));
    }

    @Override
    public void failed(Throwable exc, AIOServerThread aioServerThread) {
        System.out.println("服务器的连接处理失败...");
        // 解除阻塞状态
        aioServerThread.getCountDownLatch().countDown();
    }
}

// AIO处理线程
class AIOServerThread implements Runnable {

    // 监听端口
    private static final int PORT = 9999;

    // 服务器端关闭阻塞
    private CountDownLatch countDownLatch = null;

    // 服务器端通道
    private AsynchronousServerSocketChannel asynchronousServerSocketChannel = null;

    public AIOServerThread() throws IOException {
        // 服务器端阻塞线程数
        this.countDownLatch = new CountDownLatch(1);

        // 异步通道
        this.asynchronousServerSocketChannel = AsynchronousServerSocketChannel.open();

        // 绑定端口
        this.asynchronousServerSocketChannel.bind(new InetSocketAddress(PORT));

        System.out.println("服务器启动成功,在" + PORT + "端口上进行监听,等待客户端连接...");
    }

    public CountDownLatch getCountDownLatch() {
        return countDownLatch;
    }

    public AsynchronousServerSocketChannel getAsynchronousServerSocketChannel() {
        return asynchronousServerSocketChannel;
    }

    /**
     * 线程启动
     */
    @Override
    public void run() {
        // 等待连接
        this.asynchronousServerSocketChannel.accept(this, new AcceptHandler());
        try {
            // 保持连接
            this.countDownLatch.await();
            System.err.println("服务器的连接失败,服务器停止运行...");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

1-2_1、定义工具类:

package com.mydemo;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class InputUtil {

    // 键盘缓冲输入流
    private static final BufferedReader KEYBOARD_INPUT = new BufferedReader(
            new InputStreamReader(System.in)
    );

    // 键盘接收数据
    public InputUtil() {
    }

    // 键盘接收数据
    public static String getString(String prompt) throws IOException {

        // 输入标记
        boolean flag = true;

        // 接收输入字符串
        String str = null;

        while (flag){
            // 提示信息
            System.out.println(prompt);

            // 读取数据
            str = KEYBOARD_INPUT.readLine();

            // 保证不为null
            if(str == null || "".equals(str)){
                System.out.println("数据输入有误,请重新输入~~~");
            }else{
                flag = false;
            }
        }
        return str;
    }
}

1-2_2、定义客户端:

package com.mydemo;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.channels.CompletionHandler;
import java.util.concurrent.CountDownLatch;

public class AIOClient {

    public static void main(String[] args) throws IOException {

        //
        AIOClientThread aioClientThread = new AIOClientThread();

        // 启动客户端线程
        new Thread(aioClientThread).start();

        while (aioClientThread.sendMessage(InputUtil.getString("请输入要发送的消息:"))){
            ;
        }
    }
}

class ClientReadHandler implements CompletionHandler<Integer, ByteBuffer> {

    // 线程同步
    private CountDownLatch countDownLatch;

    // 客户端连接
    private AsynchronousSocketChannel asynchronousSocketChannel_Client = null;

    public ClientReadHandler(CountDownLatch countDownLatch, AsynchronousSocketChannel asynchronousSocketChannel_Client) {
        this.countDownLatch = countDownLatch;
        this.asynchronousSocketChannel_Client = asynchronousSocketChannel_Client;
    }

    @Override
    public void completed(Integer result, ByteBuffer byteBuffer) {

        // 重置缓冲区
        byteBuffer.flip();

        // 读取返回内容
        String receiveMessage = new String(byteBuffer.array(), 0, byteBuffer.remaining());

        // 输出回应数据
        System.err.println(receiveMessage);
    }

    @Override
    public void failed(Throwable exc, ByteBuffer attachment) {
        System.out.println("什么鬼,发送出现了问题,该客户端被关闭了...");
        try {
            this.asynchronousSocketChannel_Client.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

        // 解除阻塞状态
        this.countDownLatch.countDown();
    }
}

class ClientWriteHandler implements CompletionHandler<Integer, ByteBuffer> {

    // 线程同步
    private CountDownLatch countDownLatch;

    // 客户端连接
    private AsynchronousSocketChannel asynchronousSocketChannel_Client = null;

    public ClientWriteHandler(CountDownLatch countDownLatch, AsynchronousSocketChannel asynchronousSocketChannel_Client) {
        this.countDownLatch = countDownLatch;
        this.asynchronousSocketChannel_Client = asynchronousSocketChannel_Client;
    }

    @Override
    public void completed(Integer result, ByteBuffer byteBuffer) {
        // 有数据发送
        if(byteBuffer.hasRemaining()){
            // 数据发送
            this.asynchronousSocketChannel_Client.write(byteBuffer, byteBuffer,this);
        }else{  // 需要读取
            // 读取数据
            ByteBuffer byteBuffer_Read = ByteBuffer.allocate(100);
            // 读取回调
            this.asynchronousSocketChannel_Client.read(
                    byteBuffer_Read,
                    byteBuffer_Read,
                    new ClientReadHandler(this.countDownLatch, this.asynchronousSocketChannel_Client)
            );
        }
    }

    @Override
    public void failed(Throwable exc, ByteBuffer byteBuffer) {
        System.out.println("不科学,发送出现了问题,该客户端被关闭了...");
        try {
            this.asynchronousSocketChannel_Client.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 解除阻塞状态
        this.countDownLatch.countDown();
    }
}

// 客户端线程类
class AIOClientThread implements Runnable{

    // 连接主机
    public static final String HOST = "localhost";

    // 绑定端口
    private static final int PORT = 9999;

    // 线程锁定
    private CountDownLatch countDownLatch;

    // 客户端连接
    private AsynchronousSocketChannel asynchronousSocketChannel_Client = null;

    public AIOClientThread() throws IOException {
        // 客户端Channel
        this.asynchronousSocketChannel_Client = AsynchronousSocketChannel.open();

        // 进行客户端连接
        this.asynchronousSocketChannel_Client.connect(new InetSocketAddress(HOST, PORT));

        // 阻塞处理
        this.countDownLatch = new CountDownLatch(1);
    }

    /**
     * 实现消息发送
     * @param msg
     * @return
     */
    public boolean sendMessage(String msg){

        // 开辟缓冲区
        ByteBuffer byteBuffer = ByteBuffer.allocate(100);

        // 保存发送内容
        byteBuffer.put(msg.getBytes());

        // 重设缓冲区
        byteBuffer.flip();

        // 缓冲区输出
        this.asynchronousSocketChannel_Client.write(
                byteBuffer,
                byteBuffer,
                new ClientWriteHandler(this.countDownLatch, this.asynchronousSocketChannel_Client)
        );

        if("exit".equalsIgnoreCase(msg)){
            // 结束指令
            return false;
        }

        return true;
    }

    @Override
    public void run() {
        try {
            // 等待处理
            this.countDownLatch.await();

            // 关闭客户端
            this.asynchronousSocketChannel_Client.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值