NIO概述及實例(時鍾服務器)


NIO,非阻塞IO,重點是非阻塞而不是異步!

NIO的一般實現如下:

package com.pt.nio;

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.text.SimpleDateFormat;
import java.util.Date;
import java.util.Iterator;
import java.util.Set;

/**
 * @author panteng
 * @description 時鍾服務器
 * @date 17-3-10.
 */
public class NioServer {
    public static void main(String[] arges) throws Exception {
        char name = 'A';
        // 創建通道,並設置非阻塞
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        serverSocketChannel.configureBlocking(false);
        // 創建選擇器,並為通道綁定感興趣的事件
        Selector selector = Selector.open();
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT).attach("主監聽通道");
        System.out.println("監聽的channel Id:" + serverSocketChannel.hashCode());
        // 通道綁定端口號
        InetSocketAddress inetSocketAddress = new InetSocketAddress("127.0.0.1", 4700);
        serverSocketChannel.socket().bind(inetSocketAddress);
        // 開始輪詢通道事件
        while (true) {
            // 可以是阻塞,非阻塞,也可以設置超時
            int readyChannels = selector.selectNow();
            if (readyChannels > 0) {
                Set<SelectionKey> readyKeys = selector.selectedKeys();
                Iterator iterator = readyKeys.iterator();
                while (iterator.hasNext()) {
                    SelectionKey readyKey = (SelectionKey) iterator.next();
                    iterator.remove();
                    if (readyKey.isAcceptable()) {
                        ServerSocketChannel readyChannel = (ServerSocketChannel) readyKey.channel();
                        System.out.println("可接受連接的channel Id:" + readyChannel.hashCode() + readyKey.attachment());
                        SocketChannel socketChannel1 = (SocketChannel) readyChannel.accept().configureBlocking(false);
                        System.out.println("接受連接后返回的channel Id" + socketChannel1.hashCode());
                        socketChannel1.register(selector, (SelectionKey.OP_READ | SelectionKey.OP_WRITE)).attach(name);
                        name++;
                    }

                    if (readyKey.isWritable()) {
                        SocketChannel readyChannel = (SocketChannel) readyKey.channel();
                        ByteBuffer buffer = ByteBuffer.allocate(512);
                        buffer.put(("to " + readyKey.attachment() + " " + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + "\n")
                                .getBytes());
                        buffer.flip();
                        readyChannel.write(buffer);
                    }

                    if (readyKey.isReadable()) {
                        SocketChannel readyChannel = (SocketChannel) readyKey.channel();
                        ByteBuffer buffer = ByteBuffer.allocate(512);
                        readyChannel.read(buffer);
                        System.out.println(readyKey.attachment() + " " + getString(buffer));
                    }
                }
            }
            Thread.sleep(1000);
        }
    }

    /**
     * ByteBuffer 轉換 String
     * 
     * @param buffer
     * @return
     */
    public static String getString(ByteBuffer buffer) {
        String string = "";
        try {
            for (int i = 0; i < buffer.position(); i++) {
                string += (char) buffer.get(i);
            }
            return string;
        } catch (Exception ex) {
            ex.printStackTrace();
            return "";
        }
    }
}

此服務器有一個監聽通道,時刻監聽是否有客戶端連接;如果有,則在accept()的時候,返回一個新通道,作為一個連接!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM