日期:2014-05-20  浏览次数:20821 次

Java NIO 一直接收OP_ACCEPT的问题
Java code

import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.nio.channels.ClosedChannelException;
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;


public class TCP {

    ServerSocketChannel socketChannel;
    Selector selector;
    int port = 8778;
    String[] opsName=new String[17];
    public TCP(){
        opsName[SelectionKey.OP_ACCEPT]="OP_ACCEPT";
        opsName[SelectionKey.OP_CONNECT]="OP_CONNECT";
        opsName[SelectionKey.OP_READ]="OP_READ";
        opsName[SelectionKey.OP_WRITE]="OP_WRITE";
        try {
            socketChannel=ServerSocketChannel.open();
            socketChannel.configureBlocking(false);
            socketChannel.socket().setReuseAddress(true);
            socketChannel.socket().bind(new InetSocketAddress(port));
            selector=Selector.open();
            System.out.println(socketChannel.hashCode());
            
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    public void start(){
        try {
            socketChannel.register(selector, SelectionKey.OP_ACCEPT);
        } catch (ClosedChannelException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }
        System.out.println("server start port "+port);
        while(true){
            
            int n;
            try {
                System.out.print("wait...");
                n = selector.select(60000);
                System.out.println(n);
                if(n<=0)continue;
                
                Iterator<SelectionKey> it = selector.selectedKeys().iterator();
                while(it.hasNext()){
                    SelectionKey key = it.next();
                    it.remove();
                    System.out.println("key:"+opsName[key.interestOps()]+","+key.channel().hashCode());
                    if(key.isReadable()){
                        System.out.println(key.hashCode()+" isReadable");
                        socketChannel.accept().register(selector, SelectionKey.OP_READ);
                    //问题2:socketChannel 与 (SocketChannel)socketChannel.accept() 这两个channel什么区别
                    }
                    
                    else if(key.isAcceptable()){
                        //问题1:当一个客户端连接进来时,为什么这句话会一直重复地打印
                        System.out.println(key.hashCode()+" accepted");
                    }
                    
                }
                
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            
        }
    }

    public static void main(String[] args) {
        TCP tcp = new TCP();
        tcp.start();
    }
}




------解决方案--------------------
我晕。。。没仔细看你代码,你这代码整个逻辑都有问题
你在key.isAcceptable()里面没有做任何操作,实际上就是你根本就没有建立连接
该channel一直处于就绪状态,即使remove掉把selectedKey里面删除了,keys里面还是存在
下次select发现状态还是就绪就继续选择出来
你应该在key.isAcceptable()里面accept,然后将返回的socketChannel置为可读key