簡體   English   中英

Java NIO異步讀寫操作

[英]Java NIO asynchronous read and write operations

我正在為一個項目開發一個 NIO 服務器,該服務器將來自客戶端的消息作為輸入,其中包含讀取和寫入操作的運行時間。 我有一個問題,因為在第一次執行客戶端時一切正常,但是如果我再次運行客戶端,服務器就會卡在可寫部分。 你能告訴我我做錯了什么嗎? 這些是我的文件,提前謝謝你。

MyAsyncProcessor.java

public class MyAsyncProcessor {

    enum States {
        Idle,
        Read,
        Write
    }

    ExecutorService pool;
    private Map<Integer, States> socketStates = new HashMap<>();

    public MyAsyncProcessor() {
    }

    public static void main(String[] args) throws IOException {
        new MyAsyncProcessor().process();
    }

    public void process() throws IOException {
        pool = Executors.newFixedThreadPool(2);
        InetAddress host = InetAddress.getByName("localhost");
        Selector selector = Selector.open();
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        serverSocketChannel.configureBlocking(false);
        serverSocketChannel.bind(new InetSocketAddress(host, 9876));
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
        SelectionKey key;
        while (true) {
            if (selector.select() > 0) {
                Set<SelectionKey> selectedKeys = selector.selectedKeys();
                Iterator<SelectionKey> i = selectedKeys.iterator();
                while (i.hasNext()) {
                    key = i.next();
                    i.remove();
                    MyTask task = new MyTask();
                    if (key.isAcceptable()) {
                        SocketChannel socketChannel = serverSocketChannel.accept();
                        socketChannel.configureBlocking(false);
                        System.out.println("Channel hashCode: " + socketChannel.hashCode());
                        socketChannel.register(selector, SelectionKey.OP_READ + SelectionKey.OP_WRITE);
                        socketStates.put(socketChannel.hashCode(), States.Idle);
                        System.out.println("Connection accepted from: " + socketChannel.getLocalAddress());
                    }
                    if (key.isReadable()) {
                        System.out.println("Readable");
                        SocketChannel socketChannel = (SocketChannel) key.channel();
                        States socketState = socketStates.get(socketChannel.hashCode());
                        if (socketState == States.Idle) {
                            socketStates.put(socketChannel.hashCode(), States.Read);
                            ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
                            try {
                                socketChannel.read(byteBuffer);
                                String result = new String(byteBuffer.array()).trim();
                                String[] words = result.split(" ");
                                int secondsToRead = Integer.parseInt(words[words.length - 2])*1000;
                                int secondsToWrite = Integer.parseInt(words[words.length - 1])*1000;
                                task.setTimeToRead(secondsToRead);
                                task.setTimeToWrite(secondsToWrite);
                                System.out.println(task.getTimeToRead() + " " + task.getTimeToWrite());
                                Runnable h = new MyAsyncReadThread(task);
                                pool.execute(h);
                                socketChannel.register(selector, SelectionKey.OP_WRITE);
                            } catch (Exception e) {
                                System.out.println("Closing Connection Read...");
                            }
                        }
                    }
                    if (key.isWritable()) {
                        System.out.println("Writable");
                        SocketChannel socketChannel = (SocketChannel) key.channel();
                        States socketState = socketStates.get(socketChannel.hashCode());
                        if (socketState == States.Read) {
                            socketStates.put(socketChannel.hashCode(), States.Write);
                            System.out.println(task.getTimeToRead() + " " + task.getTimeToWrite());
                            Runnable h = new MyAsyncWriteThread(task);
                            pool.execute(h);
                        }
                        key.cancel();
                    }
                }
            }
        }
    }
}

我的客戶.java

public class MyClient  {

    public static void main(String [] args) {

        Random rand = new Random();
        int secondsToRead = rand.nextInt(10);
        int secondsToWrite = secondsToRead + 1;
        String message = "Seconds for the task to be read and written: " + secondsToRead + " " + secondsToWrite;
        System.out.println(message);
        Socket socket;
        try {
            socket = new Socket("127.0.0.1", 9876);
            PrintWriter printWriter = new PrintWriter(socket.getOutputStream(), true);
            printWriter.println(message);
            System.out.println("Sending message");
        } catch (IOException e) {
            System.out.println("Error in Socket");
            System.exit(-1);
        }
    }
}




對不起,我不能發表評論。

你不能使用key.cancel(); ,我不了解你的業務,我只能建議不要那樣使用 Map。

JDK.NIO很難。 這是您的代碼(稍作更改),希望對您有用。

不要自己寫NIO代碼買。 [https://.netty.io/][Netty] 很好。

import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @author chenshun00@gmail.com
 * @since 2022/12/13 09:46
 */
public class MyAsyncProcessor {

    enum States {
        Idle,
        Read,
        Write
    }

    ExecutorService pool;
    private Map<Integer, States> socketStates = new HashMap<>();

    public MyAsyncProcessor() {
    }

    public static class MyTask implements Runnable {

        @Override
        public void run() {
            System.out.println("execute task");
        }

        private int secondsToRead;
        private int secondsToWrite;

        public void setTimeToRead(int secondsToRead) {
            this.secondsToRead = secondsToRead;
        }

        public void setTimeToWrite(int secondsToWrite) {
            this.secondsToWrite = secondsToWrite;
        }
    }

    public static void main(String[] args) throws IOException {
        new MyAsyncProcessor().process();
    }

    public void process() throws IOException {
        pool = Executors.newFixedThreadPool(2);
        InetAddress host = InetAddress.getByName("localhost");
        Selector selector = Selector.open();
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        serverSocketChannel.configureBlocking(false);
        serverSocketChannel.bind(new InetSocketAddress(host, 9876));
        final SelectionKey register1 = serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
        register1.attach(serverSocketChannel);
        SelectionKey key;
        while (true) {
            if (selector.select() > 0) {
                Set<SelectionKey> selectedKeys = selector.selectedKeys();
                Iterator<SelectionKey> i = selectedKeys.iterator();
                while (i.hasNext()) {
                    key = i.next();
                    i.remove();
                    MyTask task = new MyTask();
                    if (!key.isValid()) {
                        key.cancel();
                        continue;
                    }
                    if (key.isAcceptable()) {
                        SocketChannel socketChannel = serverSocketChannel.accept();
                        socketChannel.configureBlocking(false);
                        System.out.println("Channel hashCode: " + socketChannel.hashCode());
                        final SelectionKey register = socketChannel.register(selector, SelectionKey.OP_READ);
                        register.attach(key.attachment());
                        System.out.println("Connection accepted from: " + socketChannel.getLocalAddress());
                    }
                    if (key.isReadable()) {
                        System.out.println("Readable");
                        SocketChannel socketChannel = (SocketChannel) key.channel();
                        socketStates.put(socketChannel.hashCode(), States.Read);


                        ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
                        try {
                            final int read = socketChannel.read(byteBuffer);
                            if (read > 0) {
                                System.out.println("receive message form client:" + new String(byteBuffer.array(), 0, read - 1));
                                task.setTimeToRead(10);
                                task.setTimeToWrite(10);
                                pool.execute(task);
                            }
                            socketChannel.register(selector, SelectionKey.OP_WRITE);
                        } catch (Exception e) {
                            socketChannel.close();
                        }
                    }
                    if (key.isValid() && key.isWritable()) {
                        System.out.println("Writable");
                        SocketChannel socketChannel = (SocketChannel) key.channel();
                        try {
                            socketChannel.write(ByteBuffer.wrap("hello world!".getBytes(StandardCharsets.UTF_8)));
                            socketChannel.register(selector, SelectionKey.OP_READ);
                        } catch (IOException e) {
                            socketChannel.close();
                        }
                    }
                }
            }
        }
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM