在客户端主动关闭连接之后,按理说服务端在调用Selector的select方法时候应该是阻塞的,但是我的测试代码中却仍然能够返回,而且返回的SelectionKey的isReadable方法返回的仍然是key,但是通道中的数据已经被读取过了。不知道是不是我的客户端代码有问题,还是服务端有问题。服务端的代码使用了Recator模式,请帮忙看看。谢谢!下面是服务端的代码
[code]
package snake.test.n4;import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.util.Iterator;
import java.util.Set;public class N4 { static int port = 6666; Selector selector;
ServerSocketChannel serverSocket; public static void main(String[] args) {
try {
ServerSocketChannel ssc = ServerSocketChannel.open(); ServerSocket ss = ssc.socket();
InetSocketAddress isa = new InetSocketAddress(port);
ss.bind(isa); Dispatcher d1 = new Dispatcher();
Dispatcher d2 = new Dispatcher(); String name = "a1";
Acceptor a1 = new Acceptor(ssc, d1, name);
name = "a2";
Acceptor a2 = new Acceptor(ssc, d2, name); new Thread(d1).start();
new Thread(d2).start();
new Thread(a1).start();
new Thread(a2).start();
} catch (IOException e) {
e.printStackTrace();
} } void run() { }}package snake.test.n4;import java.nio.channels.SelectionKey;public interface Handler {
void handle(SelectionKey key);
}
package snake.test.n4;import java.io.IOException;
import java.nio.channels.SelectionKey;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;public class Acceptor implements Runnable { private ServerSocketChannel ssc;
private Dispatcher d; private int num = 0; private String name; public Acceptor(ServerSocketChannel ssc, Dispatcher d, String name) {
this.ssc = ssc;
this.d = d;
this.name = name;
} public void run() { for (;;) { try { num++;
SocketChannel sc; sc = ssc.accept(); sc.configureBlocking(false);
d.register(sc, SelectionKey.OP_READ, new RequestHandler(sc,
name + num));
} catch (IOException e) {
e.printStackTrace();
break;
} } }}
package snake.test.n4;import java.io.IOException;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.SelectableChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.util.Iterator;
import java.util.Set;public class Dispatcher implements Runnable {
private Selector sel; private Object gate = new Object(); public Dispatcher() {
try {
sel = Selector.open();
} catch (IOException e) {
e.printStackTrace();
}
} void dispatch() throws IOException { sel.select(); for (Iterator<SelectionKey> i = sel.selectedKeys().iterator(); i
.hasNext();) {
SelectionKey sk = i.next();
i.remove();
Handler h = (Handler) sk.attachment();
h.handle(sk);
} synchronized (gate) { } } void register(SelectableChannel ch, int ops, Handler h) {
try {
synchronized (gate) {
sel.wakeup();
ch.register(sel, ops, h);
} } catch (ClosedChannelException e) {
e.printStackTrace();
}
} public void run() {
for (;;) {
try {
dispatch();
} catch (IOException e) {
e.printStackTrace();
break;
}
}
}}
package snake.test.n4;import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;public class RequestHandler implements Handler { private SocketChannel sc; String name; public RequestHandler(SocketChannel sc, String name) {
this.sc = sc;
this.name = name;
} public void handle(SelectionKey sk) { sc = (SocketChannel) sk.channel();
String recvData = null;
try {
recvData = readMessage();
System.out.println(name + " " + recvData);
} catch (IOException e) {
sk.cancel();
System.out.println("Closed");
} } public String readMessage() throws IOException {
String result = null; ByteBuffer buf = ByteBuffer.allocate(16384);
buf.clear();
int nBytes = sc.read(buf); buf.flip(); // Charset charset = Charset.forName("us-ascii");
Charset charset = Charset.forName(System.getProperty("file.encoding"));
CharsetDecoder decoder = charset.newDecoder();
CharBuffer charBuffer = decoder.decode(buf);
result = charBuffer.toString(); // sc.write(buf); return result;
}
}[/code]
下面是客户端的代码[code]package snake.test.channel;import java.net.*;
import java.nio.ByteBuffer;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Date;import java.io.*;public class sendMsg { public static void main(String[] args) { try {  Socket theSocket = new Socket("127.0.0.1", 6666);

 Writer out = new OutputStreamWriter(theSocket.getOutputStream());
 Date now = new Date();

 out.write(now.toString() + "\r\n");
 out.flush();
 theSocket.close();
} // end try catch (UnknownHostException ex) { System.err.println(ex); } catch (IOException ex) { System.err.println(ex); } } 
} [/code]在运行服务端之后,客户端向服务端发送了当前的时间,结果服务端的输出如下
a11 Mon Oct 22 20:38:47 CST 2007a11 
a11 
a11 
a11 
a11 
a11 
a11 
a11 
a11 
a11 
a11 
a11 
a11 
a11 
a11 
a11 
a11 
a11 
a11 
a11 
a11 
a11 
a11 
a11 
a11 
a11 
a11 
a11 
a11 
a11 
a11 
a11 
a11 
a11 
a11 
a11 
a11 
a11 
a11 
a11 
a11 
a11 
a11 
a11 
a11 
a11 
a11 
a11 
a11 
a11 
a11 
a11 
a11 
a11 
a11 
a11 
a11 
a11 
a11 
a11 
a11 
a11 
a11 
a11 
a11 
a11 
a11 
a11 
a11 
a11 
a11 
a11 
a11 
a11 
a11 
a11 
a11 
a11 
a11 
a11 
a11 
a11 
a11 
a11 
a11 
a11 
a11 
a11 
a11 
a11 
a11 
a11 
a11 
a11 
a11 
a11 
a11 
a11 
a11 
a11 

请问怎么解决这个问题??
谢谢!

解决方案 »

  1.   


    代码没贴上,重新帖[code]
     
    package snake.test.n4;   
      
    import java.io.IOException;   
    import java.net.InetSocketAddress;   
    import java.net.ServerSocket;   
    import java.nio.channels.SelectionKey;   
    import java.nio.channels.Selector;   
    import java.nio.channels.ServerSocketChannel;   
    import java.util.Iterator;   
    import java.util.Set;   
      
    public class N4 {   
      
        static int port = 6666;   
      
        Selector selector;   
        ServerSocketChannel serverSocket;   
      
        public static void main(String[] args) {   
            try {   
                ServerSocketChannel ssc = ServerSocketChannel.open();   
      
                ServerSocket ss = ssc.socket();   
                InetSocketAddress isa = new InetSocketAddress(port);   
                ss.bind(isa);   
      
                Dispatcher d1 = new Dispatcher();   
                Dispatcher d2 = new Dispatcher();   
      
                String name = "a1";   
                Acceptor a1 = new Acceptor(ssc, d1, name);   
                name = "a2";   
                Acceptor a2 = new Acceptor(ssc, d2, name);   
      
                new Thread(d1).start();   
                new Thread(d2).start();   
                new Thread(a1).start();   
                new Thread(a2).start();   
            } catch (IOException e) {   
                e.printStackTrace();   
            }   
      
        }   
      
        void run() {   
      
        }   
      
    }   
      
    package snake.test.n4;   
      
    import java.nio.channels.SelectionKey;   
      
    public interface Handler {   
        void handle(SelectionKey key);   
    }   
      
    package snake.test.n4;   
      
    import java.io.IOException;   
    import java.nio.channels.SelectionKey;   
    import java.nio.channels.ServerSocketChannel;   
    import java.nio.channels.SocketChannel;   
      
    public class Acceptor implements Runnable {   
      
        private ServerSocketChannel ssc;   
        private Dispatcher d;   
      
        private int num = 0;   
      
        private String name;   
      
        public Acceptor(ServerSocketChannel ssc, Dispatcher d, String name) {   
            this.ssc = ssc;   
            this.d = d;   
            this.name = name;   
        }   
      
        public void run() {   
      
            for (;;) {   
      
                try {   
      
                    num++;   
                    SocketChannel sc;   
      
                    sc = ssc.accept();   
      
                    sc.configureBlocking(false);   
                    d.register(sc, SelectionKey.OP_READ, new RequestHandler(sc,   
                            name + num));   
                } catch (IOException e) {   
                    e.printStackTrace();   
                    break;   
                }   
      
            }   
      
        }   
      
    }   
      
    package snake.test.n4;   
      
    import java.io.IOException;   
    import java.nio.channels.ClosedChannelException;   
    import java.nio.channels.SelectableChannel;   
    import java.nio.channels.SelectionKey;   
    import java.nio.channels.Selector;   
    import java.util.Iterator;   
    import java.util.Set;   
      
    public class Dispatcher implements Runnable {   
        private Selector sel;   
      
        private Object gate = new Object();   
      
        public Dispatcher() {   
            try {   
                sel = Selector.open();   
            } catch (IOException e) {   
                e.printStackTrace();   
            }   
        }   
      
        void dispatch() throws IOException {   
      
            sel.select();   
      
            for (Iterator<SelectionKey> i = sel.selectedKeys().iterator(); i   
                    .hasNext();) {   
                SelectionKey sk = i.next();   
                i.remove();   
                Handler h = (Handler) sk.attachment();   
                h.handle(sk);   
            }   
      
            synchronized (gate) {   
      
            }   
      
        }   
      
        void register(SelectableChannel ch, int ops, Handler h) {   
            try {   
                synchronized (gate) {   
                    sel.wakeup();   
                    ch.register(sel, ops, h);   
                }   
      
            } catch (ClosedChannelException e) {   
                e.printStackTrace();   
            }   
        }   
      
        public void run() {   
            for (;;) {   
                try {   
                    dispatch();   
                } catch (IOException e) {   
                    e.printStackTrace();   
                    break;   
                }   
            }   
        }   
      
    }   
      
    package snake.test.n4;   
      
    import java.io.IOException;   
    import java.nio.ByteBuffer;   
    import java.nio.CharBuffer;   
    import java.nio.channels.SelectionKey;   
    import java.nio.channels.SocketChannel;   
    import java.nio.charset.Charset;   
    import java.nio.charset.CharsetDecoder;   
      
    public class RequestHandler implements Handler {   
      
        private SocketChannel sc;   
      
        String name;   
      
        public RequestHandler(SocketChannel sc, String name) {   
            this.sc = sc;   
            this.name = name;   
        }   
      
        public void handle(SelectionKey sk) {   
      
            sc = (SocketChannel) sk.channel();   
            String recvData = null;   
            try {   
                recvData = readMessage();   
                System.out.println(name + " " + recvData);   
      
            } catch (IOException e) {   
                sk.cancel();   
                System.out.println("Closed");   
            }   
      
        }   
      
        public String readMessage() throws IOException {   
            String result = null;   
      
            ByteBuffer buf = ByteBuffer.allocate(16384);   
            buf.clear();   
            int nBytes = sc.read(buf);   
      
            buf.flip();   
      
            // Charset charset = Charset.forName("us-ascii");   
            Charset charset = Charset.forName(System.getProperty("file.encoding"));   
            CharsetDecoder decoder = charset.newDecoder();   
            CharBuffer charBuffer = decoder.decode(buf);   
            result = charBuffer.toString();   
      
            // sc.write(buf);   
      
            return result;   
        }   
    }   
      
    [/code]下面是客户端的代码
    [code]
      
    package snake.test.channel;   
      
    import java.net.*;   
    import java.nio.ByteBuffer;   
    import java.nio.channels.Selector;   
    import java.nio.channels.SocketChannel;   
    import java.util.Date;   
      
    import java.io.*;   
      
    public class sendMsg {   
      
        public static void main(String[] args) {   
      
            try {   
      
                 Socket theSocket = new Socket("127.0.0.1", 6666);   
                   
                 Writer out = new OutputStreamWriter(theSocket.getOutputStream());   
                 Date now = new Date();   
                   
                 out.write(now.toString() + "\r\n");   
                 out.flush();   
      
                   
                 theSocket.close();        
            } // end try   
      
            catch (UnknownHostException ex) {   
      
                System.err.println(ex);   
      
            }   
      
            catch (IOException ex) {   
      
                System.err.println(ex);   
      
            }   
      
        }    
    }    
      [/code]
      

  2.   

    帮你顶下,我也遇到同样的问题这个是我的代码,不过是客户端private static void client(){
    try{
    Selector selector=Selector.open();
    InetSocketAddress isa=new InetSocketAddress("www.ah.xinhuanet.com",80);
    SocketChannel sc=SocketChannel.open(isa);
    sc.configureBlocking(false);
    sc.register(selector, SelectionKey.OP_WRITE|SelectionKey.OP_READ);
    int keyn;
    while((keyn=selector.select())>0){
    Set readykey=selector.selectedKeys();
    Iterator it=readykey.iterator();
    while(it.hasNext()){
    SelectionKey skey=(SelectionKey)it.next();
    it.remove();
    SocketChannel scc=(SocketChannel)skey.channel();
    if((skey.readyOps()&SelectionKey.OP_WRITE)==SelectionKey.OP_WRITE){
    System.out.println("ddd1");
    if(!scc.isConnected()) break;
    String head="GET / HTTP/1.1\r\n" +
            "Connection: close\r\n" +
            "Host: www.ah.xinhuanet.net\r\n" +
            "\r\n";
    ByteBuffer bbf=ByteBuffer.wrap(head.getBytes());
    scc.write(bbf);
    //scc.close();
    }

    if((skey.readyOps()&SelectionKey.OP_READ)==SelectionKey.OP_READ){
    System.out.println("ddd2");
    ByteBuffer bff=ByteBuffer.allocate(1024);
    bff.flip();
    int n=scc.read(bff);
    if(n>0&&n==bff.limit()){
    System.out.print(bff.toString());
    }
    }
    }
    readykey.clear();
    }
    }catch(IOException e){
    e.printStackTrace();
    }
    }还有 就是 scc.write(bbf); 的时候,出异常。不知道了
      

  3.   

    推荐看下mina的nio代码
    http://mina.apache.org