package com.selector; import org.junit.Test; import java.io.IOException; import java.net.InetSocketAddress; import java.net.ServerSocket; import java.net.Socket; import java.nio.ByteBuffer; import java.nio.channels.*; import java.util.Iterator; /** * Created by wang on 15-3-26. */ public class SelectorSocket { private int PORT = 8888; private ByteBuffer byteBuffer = ByteBuffer.allocate(1024); @Test public void selectSocket() throws IOException, InterruptedException { System.out.println("listening on port "+PORT); ServerSocketChannel serverSocketChannel = ServerSocketChannel.open(); serverSocketChannel.configureBlocking(false); ServerSocket serverSocket = serverSocketChannel.socket(); serverSocket.bind(new InetSocketAddress(PORT)); Selector selector = Selector.open(); serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT); while (true){ int n = selector.select(); if (n == 0){ continue; } Iterator iterator = selector.selectedKeys().iterator(); while (iterator.hasNext()){ SelectionKey key = (SelectionKey) iterator.next(); if (key.isAcceptable()){ ServerSocketChannel server = (ServerSocketChannel) key.channel(); SocketChannel socketChannel = server.accept(); registeChannel(selector,socketChannel,SelectionKey.OP_READ); sayHello(socketChannel); } else if (key.isReadable()){ System.out.println(" ready to read"); readDateFromSocket(key); } iterator.remove(); } } } private void registeChannel(Selector selector,SelectableChannel channel , int ops) throws IOException { channel.configureBlocking(false); channel.register(selector,ops); } private void sayHello(SocketChannel channel) throws IOException { byteBuffer.clear(); byteBuffer.put("Hello , You Have Connected on Server !".getBytes()); byteBuffer.flip(); channel.write(byteBuffer); } private void readDateFromSocket(SelectionKey key) throws IOException { SocketChannel socketChannel = (SocketChannel) key.channel(); Socket socket = socketChannel.socket(); int count; byteBuffer.clear(); while ((count = socketChannel.read(byteBuffer))>0 ){ System.out.println("the buffer size is > 0"); byteBuffer.flip(); while (byteBuffer.hasRemaining()){ System.out.print((char)byteBuffer.get() ); } System.out.println(" on Port :"+ socket.getPort()); byteBuffer.clear(); } if (count < 0){ socketChannel.close(); } } }
java使用epoll默认会使用水平触发,即如果有事件发生,如果你不处理,那么下次还会触发
但经过java 中EPollSelectorImpl实现之后有了小小的变化,如果某个事件发生,你不做任何处理,那么下次调用select的时候,虽然底层epoll仍然会返回事件,但上面的代码会判断本次事件和上次事件是否一致,如果是一样,java认为没有事件发生,如果要做到一致,必须将selectedKeys中的key删掉,否则会有差别,所以请注意selectedKeys删除的重要性!否则会死循环!