SocketChannel 例子2

Java NIO非堵塞技术实际是采取Reactor模式,或者说是Observer模式为我们监察I/O端口,如果有内容进来,会自动通知我们。

在服务端我们可以使用非阻塞的方式。 下面是一段server端的程序。 client 可以采用阻塞方式来请求。

 

NIO 有一个主要的类Selector,这个类似一个观察者,只要我们把需要探知的socketchannel告诉Selector,我们接着做别的事情,当有事件发生时,他会通知我们,传回一组SelectionKey, 我们读取这些Key, 就会获得我们刚刚注册过的socketchannel,然后,我们从 这个Channel中读取数据,放心,包准能够读到,接着我们可以处理这些数据。

Selector内部原理实际是在做一个对所注册的channel的轮询访问,不断的轮询(目前就这一个算法),一旦轮询到一个channel有所注册的事情发生,比如数据来了,他就会站起来报告,交出一把钥匙,让我们通过这把钥匙来读取这个channel的内容。

 

做一个备忘吧。

 

package com.jimmy.nio;

import java.io.IOException;
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.util.Date;
import java.util.Iterator;

public class NoBlockServerSocket {

    private Selector selector;

    private ByteBuffer byteBuffer=ByteBuffer.allocate(1024);

    public NoBlockServerSocket(int port) throws IOException {
        selector=Selector.open();
        ServerSocketChannel serverSocketChannel=ServerSocketChannel.open();//创建nio通道
        serverSocketChannel.socket().bind(new InetSocketAddress(port));//创建基于nio通道的socket链接绑定
        serverSocketChannel.configureBlocking(false);//配置使通道不阻塞
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);//将通道绑定到选择器
    }

    public Selector getSelector() {
        return selector;
    }

    public void setSelector(Selector selector) {
        this.selector=selector;
    }

    public void listen() {

        try {
            for(;;) {

                int i=selector.select();//获取通道内关心事件的集合。
                if(i<1){
                    continue;
                }
                //Selector传回一组SelectionKeys
                Iterator<SelectionKey> iter=selector.selectedKeys().iterator();
                if(iter.hasNext()) {
                    SelectionKey selectionKey=iter.next();
                    //一个key被处理完成后,就都被从就绪关键字(ready keys)列表中除去
                    iter.remove();
                    process(selectionKey);
                }
                System.out.println(" loop " + new Date());
            }
        } catch(IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    public void process(SelectionKey selectionKey) throws IOException {
        System.out.println("selectionKey.isAcceptable()"+selectionKey.isAcceptable());
        System.out.println("selectionKey.isReadable()"+selectionKey.isReadable());
        System.out.println("selectionKey.isWritable()"+selectionKey.isWritable());
       
        if(selectionKey.isAcceptable()) {//获得客户端链接,并注册到选择器中,观察的动作有读写。
            ServerSocketChannel server=(ServerSocketChannel)selectionKey.channel();
            SocketChannel socketChannel=server.accept();
            socketChannel.configureBlocking(false);
            socketChannel.register(selector, SelectionKey.OP_READ | SelectionKey.OP_WRITE);
            System.out.println("accept:" + selectionKey.interestOps() + " " + selectionKey.readyOps());
        } else if(selectionKey.isReadable()) {//这个通道是一个可读的状态。进行读取操作
            SocketChannel channel=(SocketChannel)selectionKey.channel();
            int count=channel.read(byteBuffer);
            if(count > 0) {
                byteBuffer.flip();
                byte[] bbb=byteBuffer.array();
                System.out.println("i receive" + new String(bbb, 0, count));
                byteBuffer.clear();
            }
        } else if(selectionKey.isWritable()) {//这个通道是一个可以写的状态,进行写入的操作
            System.out.println("isWritable:" + selectionKey.interestOps());
            SocketChannel channel=(SocketChannel)selectionKey.channel();
            byteBuffer.clear();
            byteBuffer.put(new Date().toString().getBytes());
            byteBuffer.flip();
            channel.write(byteBuffer);
            channel.close();
            byteBuffer.clear();
        }
        System.out.println("\n\n\n");
    }

    public static void main(String[] args) {
        int port=8888;
        try {
            NoBlockServerSocket server=new NoBlockServerSocket(port);
            System.out.println("listening on " + port);
            server.listen();
        } catch(IOException e) {
            e.printStackTrace();
        }
    }
}

 

 

你可能感兴趣的:(java,nio)