Java异步通信实现

参考链接:

[1] java aio 编程

[2] java AIO 服务端代码实现

主要内容:

实现服务端、客户端异步多次通信。

服务端代码:

package com.aio;

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.nio.charset.Charset;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

/**
 * java AIO 服务端代码实现
 * https://blog.csdn.net/qq_29048719/article/details/81045258
 */
public class AIOServer {
    
    
    public final static int PORT = 9888;
    private AsynchronousServerSocketChannel server;
    private AsynchronousSocketChannel lastClient; // 最后一次连接的客户端

    public AIOServer() throws IOException {
    
    
        server = AsynchronousServerSocketChannel.open().bind(
                new InetSocketAddress(PORT));
    }

    /**
     * Future方式
     * @throws InterruptedException
     * @throws ExecutionException
     * @throws TimeoutException
     */
    public void startWithFuture() throws InterruptedException,
            ExecutionException, TimeoutException {
    
    
        while (true) {
    
    // 循环接收客户端请求
            Future<AsynchronousSocketChannel> future = server.accept();
            AsynchronousSocketChannel socket = future.get();// get() 是为了确保 accept 到一个连接
            handleWithFuture(socket);
        }
    }
    public void handleWithFuture(AsynchronousSocketChannel channel) throws InterruptedException, ExecutionException, TimeoutException {
    
    
        ByteBuffer readBuf = ByteBuffer.allocate(2);
        readBuf.clear();

        while (true) {
    
    // 一次可能读不完
            //get 是为了确保 read 完成,超时时间可以有效避免DOS攻击,如果客户端一直不发送数据,则进行超时处理
            Integer integer = channel.read(readBuf).get(100000, TimeUnit.SECONDS);
            System.out.println("read: " + integer);
            if (integer == -1) {
    
    
                break;
            }
            readBuf.flip();
            System.out.println("received: " + Charset.forName("UTF-8").decode(readBuf));
            readBuf.clear();
        }
    }

    /**
     * Callback方式
     * @throws InterruptedException
     * @throws ExecutionException
     * @throws TimeoutException
     */
    public void startWithCompletionHandler() throws InterruptedException,
            ExecutionException, TimeoutException {
    
    
        server.accept(null,
                new CompletionHandler<AsynchronousSocketChannel, Object>() {
    
    
                    public void completed(AsynchronousSocketChannel result, Object attachment) {
    
    
                        server.accept(null, this);// 再次接收客户端连接
                        handleWithCompletionHandler(result);

                        lastClient = result;
                    }

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

    public void handleWithCompletionHandler(final AsynchronousSocketChannel channel) {
    
    
        try {
    
    
            final ByteBuffer buffer = ByteBuffer.allocate(2048);
            final long timeout = 30L;
            channel.read(buffer, timeout, TimeUnit.MINUTES, null, new CompletionHandler<Integer, Object>() {
    
    
                @Override
                public void completed(Integer result, Object attachment) {
    
    
                    System.out.println("read:" + result);
                    if (result == -1) {
    
    
                        try {
    
    
                            channel.close();
                        } catch (IOException e) {
    
    
                            e.printStackTrace();
                        }
                        return;
                    }
                    buffer.flip();
                    System.out.println("received message from client:" + Charset.forName("UTF-8").decode(buffer));
                    buffer.clear();
                    // 再次等待读取客户端消息
                    channel.read(buffer, timeout, TimeUnit.MINUTES, null, this);
                }

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

    public static void main(String args[]) throws Exception {
    
    
        // new AIOServer().startWithFuture();
        AIOServer aioServer = new AIOServer();
        // 使用Callback方式
        aioServer.startWithCompletionHandler();
        Thread.sleep(20000);
        aioServer.lastClient.write(ByteBuffer.wrap("服务端消息1".getBytes()));
        Thread.sleep(1000);
        aioServer.lastClient.write(ByteBuffer.wrap("服务端消息2".getBytes()));
        Thread.sleep(100000);
    }
}

客户端代码:

package com.aio;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.UnknownHostException;
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.Scanner;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class AIOClient {
    
    
    public final static int PORT = 9888;
    private AsynchronousSocketChannel asyncClient;

    public AIOClient() throws IOException {
    
    
        asyncClient = AsynchronousSocketChannel.open();
    }

    public void startWithFuture() throws InterruptedException, ExecutionException {
    
    
        asyncClient.connect(new InetSocketAddress("localhost", PORT)).get();
        handleWithCompletionHandler();
    }

    public void handleWithCompletionHandler() {
    
    
        try {
    
    
            final ByteBuffer buffer = ByteBuffer.allocate(2048);
            asyncClient.read(buffer, null, new CompletionHandler<Integer, Object>() {
    
    
                @Override
                public void completed(Integer result, Object attachment) {
    
    
                    System.out.println("read:" + result);
                    if (result == -1) {
    
    
                        return;
                    }
                    buffer.flip();
                    System.out.println("received message from server:" + Charset.forName("UTF-8").decode(buffer));
                    buffer.clear();
                    // 再次等待读取服务端消息
                    asyncClient.read(buffer, null, this);
                }

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

    public static void main(String[] args) throws IOException, ExecutionException, InterruptedException {
    
    
        // AsynchronousSocketChannel client = AsynchronousSocketChannel.open();
        // client.connect(new InetSocketAddress("localhost", 9888)).get();
        // client.write(ByteBuffer.wrap("123456789".getBytes()));
        // Thread.sleep(1000);
        // client.write(ByteBuffer.wrap("32165498".getBytes()));
        // Thread.sleep(1111111);

        AIOClient aioClient = new AIOClient();
        aioClient.startWithFuture();
        aioClient.asyncClient.write(ByteBuffer.wrap("123456789".getBytes()));
        Thread.sleep(1000);
        aioClient.asyncClient.write(ByteBuffer.wrap("32165498".getBytes()));
        Thread.sleep(200000);
    }
}

结果输出:

AIOServer

Connected to the target VM, address: '127.0.0.1:63937', transport: 'socket'
read:9
received message from client:123456789
read:8
received message from client:32165498

AIOClient

Connected to the target VM, address: '127.0.0.1:63946', transport: 'socket'
read:16
received message from server:服务端消息1
read:16
received message from server:服务端消息2

猜你喜欢

转载自blog.csdn.net/wml00000/article/details/120850304