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()的时候,返回一个新通道,作为一个连接!

posted @ 2017-03-10 11:11  沙中世界  阅读(3338)  评论(0编辑  收藏  举报