import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;/**
 * 在非阻塞模式下、只需要启动一个线程、就能同时处理3件事
 * 1、接收客户请求 
 * 2、接收客户发送的数据
 * 3、向客户发回相应数据
 */
public class Server {
private int port = 8000;
private Selector selector = null;
private ServerSocketChannel serverSocketChannel = null;

public Server() throws IOException{
selector = Selector.open();//创建一个Selector对象
serverSocketChannel = ServerSocketChannel.open();//创建一个ServerSocketChannel对象
serverSocketChannel.configureBlocking(false);//设置工作模式为非阻塞模式
serverSocketChannel.socket().bind(new InetSocketAddress(port));//把服务器进程与本地端口绑定
}

public void service() throws IOException{
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

while(selector.select()>0){
Set<SelectionKey> readKey = selector.selectedKeys();//获得Selector的selected-key集合
Iterator<SelectionKey> it = readKey.iterator();

while(it.hasNext()){
SelectionKey key = null;
try {
key = (SelectionKey) it.next();
it.remove();
if(key.isAcceptable()){
ServerSocketChannel ssc = (ServerSocketChannel)key.channel();
SocketChannel socketChannel = ssc.accept();
socketChannel.configureBlocking(false);
socketChannel.register(selector, SelectionKey.OP_READ|SelectionKey.OP_WRITE);
} if(key.isReadable()){
System.out.println("read...");
}

if(key.isWritable()){
System.out.println("write...");
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}

public static void main(String[] args) throws IOException {
new Server().service();
}
}public class Test {
public static void main(String[] args) throws Exception {
Socket socket = new Socket("127.0.0.1",8000);
}
}
打印结果:
read...
write...
read...
write...
read...
write...
read...
write...
read...

客户端并没有向服务端发送任何数据     为什么一直会有读事件

解决方案 »

  1.   

    http://stackoverflow.com/questions/4139300/socketchannel-fires-isreadable-but-nothing-to-read
    我想这个应该能解决你的问题
      

  2.   

    if(key.isReadable()){
    System.out.println("read...");
    }因为你没有把 Channel 中的数据读出来啊,只是打印了个不相干的东西。
      

  3.   

    另外,在使用 NIO 时,不要注册写事件,因为在通道中 99% 以上的时间是可写的,如果注册了会死循环地进入可写事件流。一般在真正需要向通道写入数据时临时注册写事件,在数据写完后立马注销写事件。