Java AIO implements client and server codes based on two methods (unilaterally the server receives information from the client)

In java, there are two classes of ways to support the asynchronous model:

  • Future class
  • Callable interface
    Strictly speaking, Future cannot be regarded as an asynchronous model class, because the future.get() method is blocked and needs to wait for the processing to complete; while Callable is a callback, which is an authentic asynchronous model tool.

Introduction

In Java, some APIs about using IO are provided for developers to read and write external data and files. We call these APIs Java IO. IO is a more important knowledge point in Java and a more difficult knowledge point to learn. And with the development of Java to provide better data transmission performance, there are currently three kinds of IO coexisting; they are BIO, NIO and AIO.

 

 This is mainly to record the code implementation of AIO

Based on Future


import org.junit.jupiter.api.Test;
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousServerSocketChannel;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.charset.StandardCharsets;
import java.util.Scanner;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;

/**
 * @description:
 * @create: 2021-08-26 11:18
 **/
public class BaseOnFuture {
    @Test
    public void AsynchronousServerSocketChannelServer() {
        try {
            AsynchronousServerSocketChannel channel = AsynchronousServerSocketChannel.open();
            channel.bind(new InetSocketAddress(8888));
            while (true) {
                Future<AsynchronousSocketChannel> conn = channel.accept();
                // 阻塞等待直到future有结果
                AsynchronousSocketChannel asyncSocketChannel = conn.get();
                // 异步处理连接
                asyncHandle(asyncSocketChannel);
            }
        } catch (IOException | InterruptedException | ExecutionException e) {
            e.printStackTrace();
        }
    }

    // 基于future 实际上是同步的读取方式
    private void asyncHandle(AsynchronousSocketChannel asyncSocketChannel) {
        ByteBuffer dst = ByteBuffer.allocate(1024);
        // based on Future,
        // 实际上是同步处理的方式,为了不将处理变成阻塞式单连接的socket形式,使用子线程来获取输入流
        new Thread(() -> {
            while (asyncSocketChannel.isOpen()) {
                Future<Integer> readFuture = asyncSocketChannel.read(dst);
                try {
                    // 阻塞等待读取结果
                    Integer readResult = readFuture.get();
                    if (readResult > 0) {

                        System.out.println("收到来自客户端的信息:\n"+new String(dst.array(), StandardCharsets.UTF_8));
                        dst.clear();

                    } else {
                        // doOtherthing
                    }
                } catch (InterruptedException | ExecutionException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }

    // Future
    @Test
    public void TestAsyncSocketChannelClient() {
        while(true){
            System.out.println("你想对服务器说:");
            Scanner s = new Scanner(System.in);
            String line = s.nextLine();
            AsynchronousSocketChannel asc;
            try {
                asc = AsynchronousSocketChannel.open();
                Future<Void> connResult =
                        asc.connect(new InetSocketAddress(InetAddress.getLocalHost(), 8888));
                // 等待连接成功。连接成功会返回null;
                connResult.get();
                // 读写操作
                ByteBuffer buf = ByteBuffer.wrap(line.getBytes());
                asc.write(buf).get();
                // TODO
                asc.close();
            } catch (IOException | InterruptedException | ExecutionException e) {
                e.printStackTrace();
            }
        }

    }

 manual:

1. Run the AsynchronousServerSocketChannelServer server first. At this time, the thread will always be blocked waiting for the connection

      It's running all the time, don't worry

 2. Start the client, and in the terminal terminal, enter the information you want to send to the server

 3. Check whether the server receives the information

 The description was successful

callback-based


import org.junit.jupiter.api.Test;
import java.io.IOException;
import java.net.InetAddress;
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.nio.charset.StandardCharsets;
import java.util.Scanner;
import java.util.concurrent.CountDownLatch;

/**
 * @description:
 * @create: 2021-08-26 11:19
 **/
public class BaseOnCallBack {
    @Test
    public void AsynchronousServerSocketChannelCallbackServer() {
        try {
            AsynchronousServerSocketChannel channel = AsynchronousServerSocketChannel.open();
            channel.bind(new InetSocketAddress(8888));
            channel.accept(null, new CompletionHandler<AsynchronousSocketChannel, Void>() {

                @Override
                public void completed(AsynchronousSocketChannel result, Void attachment) {
                    System.out.println("accept completed");
                    // 异步处理连接
                    asyncHandle(result);
                    // 继续监听accept
                    channel.accept(null, this);
                }

                @Override
                public void failed(Throwable exc, Void attachment) {
                    System.out.println("accept failed");
                }
            });
            // 让主线程保持存活
            while (true) {
                System.in.read();
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    // 基于回调
    private void asyncHandle(AsynchronousSocketChannel asyncSocketChannel) {
        ByteBuffer dst = ByteBuffer.allocate(1024);
        asyncSocketChannel.read(dst, null, new CompletionHandler<Integer, Void>() {

            @Override
            public void completed(Integer result, Void attachment) {
                if (result > 0) {
                    System.out.println(new String(dst.array(), StandardCharsets.UTF_8));
                    dst.clear();
                }
                // 注册回调,继续读取输入
                asyncSocketChannel.read(dst, null, this);

            }

            @Override
            public void failed(Throwable exc, Void attachment) {
                // TODO Auto-generated method stub

            }
        });
    }


    // callback
    @Test
    public void TestAsyncSocketChannelCallbackClient() {
        while(true){
            System.out.println("你想对服务器说:");
            Scanner s = new Scanner(System.in);
            String line = s.nextLine();

            CountDownLatch latch = new CountDownLatch(1);
            AsynchronousSocketChannel asc;
            try {
                asc = AsynchronousSocketChannel.open();
                asc.connect(new InetSocketAddress(InetAddress.getLocalHost(), 8888), null,
                        new CompletionHandler<Void, Void>() {

                            @Override
                            public void completed(Void result, Void attachment) {
                                System.out.println("connect complete;");
                                // 写操作
                                ByteBuffer buf = ByteBuffer.wrap(line.getBytes());
                                asc.write(buf, null, new CompletionHandler<Integer, Void>() {

                                    @Override
                                    public void completed(Integer result, Void attachment) {
                                        System.out.println("write completed,close channnl");
                                        try {
                                            latch.countDown();
                                            asc.close();
                                        } catch (IOException e) {
                                            // TODO Auto-generated catch block
                                            e.printStackTrace();
                                        }

                                    }

                                    @Override
                                    public void failed(Throwable exc, Void attachment) {
                                        try {
                                            asc.close();
                                            latch.countDown();
                                        } catch (IOException e) {
                                            // TODO Auto-generated catch block
                                            e.printStackTrace();
                                        }

                                    }
                                });

                            }

                            @Override
                            public void failed(Throwable exc, Void attachment) {
                                // TODO Auto-generated method stub

                            }
                        });
                // 等待回调结束
                latch.await();
            } catch (IOException | InterruptedException e) {
                e.printStackTrace();
            }

        }

    }
}

 The calling process based on the callback is the same as above!

Next: Java NIO server and client communicate

Guess you like

Origin blog.csdn.net/luolearn/article/details/119930554