免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2648 | 回复: 0
打印 上一主题 下一主题

为何selector一直是isWritable [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2012-07-15 21:25 |只看该作者 |倒序浏览
Java网络编程精解书中4.4.2中的例子。非阻塞模式的client用来selector,但是我加了打印发现该selector一直会返回isWritable的key,请问这是什么缘故。
client代码
  1. package com.nonblock.test;

  2. import java.io.BufferedReader;
  3. import java.io.IOException;
  4. import java.io.InputStreamReader;
  5. import java.net.InetAddress;
  6. import java.net.InetSocketAddress;
  7. import java.nio.ByteBuffer;
  8. import java.nio.CharBuffer;
  9. import java.nio.channels.SelectionKey;
  10. import java.nio.channels.Selector;
  11. import java.nio.channels.SocketChannel;
  12. import java.nio.charset.Charset;
  13. import java.util.Iterator;
  14. import java.util.Set;

  15. public class EchoClient{
  16.   private SocketChannel socketChannel = null;
  17.   private ByteBuffer sendBuffer=ByteBuffer.allocate(1024);
  18.   private ByteBuffer receiveBuffer=ByteBuffer.allocate(1024);
  19.   private Charset charset=Charset.forName("GBK");
  20.   private Selector selector;

  21.   public EchoClient()throws IOException{
  22.     socketChannel = SocketChannel.open();
  23.     InetAddress ia = InetAddress.getLocalHost();
  24.     InetSocketAddress isa = new InetSocketAddress(ia,8000);
  25.     socketChannel.connect(isa);
  26.     socketChannel.configureBlocking(false);
  27.     System.out.println("与服务器的连接建立成功");
  28.     selector=Selector.open();
  29.   }
  30.   public static void main(String args[])throws IOException{
  31.     final EchoClient client=new EchoClient();
  32.     Thread receiver=new Thread(){
  33.       public void run(){
  34.         client.receiveFromUser();
  35.       }
  36.     };

  37.     receiver.start();
  38.     client.talk();
  39.   }

  40.   public void receiveFromUser(){
  41.     try{
  42.       BufferedReader localReader=new BufferedReader(new InputStreamReader(System.in));
  43.       String msg=null;
  44.       while((msg=localReader.readLine())!=null){
  45.         synchronized(sendBuffer){
  46.                 System.out.println("receive from user");
  47.             sendBuffer.put(encode(msg + "\r\n"));
  48.          }
  49.         if(msg.equals("bye"))
  50.           break;
  51.       }
  52.     }catch(IOException e){
  53.        e.printStackTrace();
  54.     }
  55.   }

  56.   public void talk()throws IOException {
  57.      socketChannel.register(selector,
  58.                           SelectionKey.OP_READ |
  59.                           SelectionKey.OP_WRITE);
  60.      while (selector.select() > 0 ){
  61.        Set readyKeys = selector.selectedKeys();
  62.        Iterator it = readyKeys.iterator();
  63.        while (it.hasNext()){
  64.          SelectionKey key=null;
  65.          try{
  66.              key = (SelectionKey) it.next();
  67.              it.remove();

  68.              if (key.isReadable()) {
  69.                      System.out.println("触发可读监听");
  70.                      receive(key);
  71.              }
  72.              if (key.isWritable()) {
  73.                      System.out.println("触发可写监听");//此处是我加的打印!!!!!!!!!!!!!!
  74.                  send(key);
  75.              }
  76.          }catch(IOException e){
  77.             e.printStackTrace();
  78.             try{
  79.                 if(key!=null){
  80.                     key.cancel();
  81.                     key.channel().close();
  82.                 }
  83.             }catch(Exception ex){e.printStackTrace();}
  84.          }
  85.       }//#while
  86.     }//#while
  87.   }

  88.   public void send(SelectionKey key)throws IOException{
  89.     SocketChannel socketChannel=(SocketChannel)key.channel();
  90.     synchronized(sendBuffer){
  91.         sendBuffer.flip(); //把极限设为位置
  92.         //System.out.println(sendBuffer.toString());
  93.         int ret = socketChannel.write(sendBuffer);
  94.         //System.out.println("ret = " + ret);
  95.         sendBuffer.compact();
  96.      }
  97.   }
  98.   public void receive(SelectionKey key)throws IOException{
  99.     SocketChannel socketChannel=(SocketChannel)key.channel();
  100.     socketChannel.read(receiveBuffer);
  101.     receiveBuffer.flip();
  102.     String receiveData=decode(receiveBuffer);

  103.     if(receiveData.indexOf("\n")==-1)return;

  104.     String outputData=receiveData.substring(0,receiveData.indexOf("\n")+1);
  105.     System.out.print(outputData);
  106.     if(outputData.equals("echo:bye\r\n")){
  107.         key.cancel();
  108.         socketChannel.close();
  109.         System.out.println("关闭与服务器的连接");
  110.         selector.close();
  111.         System.exit(0);
  112.     }

  113.     ByteBuffer temp=encode(outputData);
  114.     receiveBuffer.position(temp.limit());
  115.     receiveBuffer.compact();
  116.   }

  117.   public String decode(ByteBuffer buffer){  //解码
  118.     CharBuffer charBuffer= charset.decode(buffer);
  119.     return charBuffer.toString();
  120.   }
  121.   public ByteBuffer encode(String str){  //编码
  122.     return charset.encode(str);
  123.   }
  124. }


  125. /****************************************************
  126. * 作者:孙卫琴                                     *
  127. * 来源:<<Java网络编程精解>>                       *
  128. * 技术支持网址:www.javathinker.org                *
  129. ***************************************************/
复制代码
server的代码:
  1. package com.nonblock.test;

  2. import java.io.IOException;
  3. import java.net.InetSocketAddress;
  4. import java.nio.ByteBuffer;
  5. import java.nio.CharBuffer;
  6. import java.nio.channels.SelectionKey;
  7. import java.nio.channels.Selector;
  8. import java.nio.channels.ServerSocketChannel;
  9. import java.nio.channels.SocketChannel;
  10. import java.nio.charset.Charset;
  11. import java.util.Iterator;
  12. import java.util.Set;

  13. public class EchoServer{
  14.   private Selector selector = null;
  15.   private ServerSocketChannel serverSocketChannel = null;
  16.   private int port = 8000;
  17.   private Charset charset=Charset.forName("GBK");

  18.   public EchoServer()throws IOException{
  19.     selector = Selector.open();
  20.     serverSocketChannel= ServerSocketChannel.open();
  21.     serverSocketChannel.socket().setReuseAddress(true);
  22.     serverSocketChannel.configureBlocking(false);
  23.     serverSocketChannel.socket().bind(new InetSocketAddress(port));
  24.     System.out.println("服务器启动");
  25.   }

  26.   public void service() throws IOException{
  27.     serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT );
  28.     while (selector.select() > 0 ){
  29.       Set readyKeys = selector.selectedKeys();
  30.       Iterator it = readyKeys.iterator();
  31.       while (it.hasNext()){
  32.          SelectionKey key=null;
  33.          try{
  34.             key = (SelectionKey) it.next();
  35.             it.remove();

  36.             if (key.isAcceptable()) {
  37.               ServerSocketChannel ssc = (ServerSocketChannel) key.channel();
  38.               SocketChannel socketChannel = (SocketChannel) ssc.accept();
  39.               System.out.println("接收到客户连接,来自:" +
  40.                                  socketChannel.socket().getInetAddress() +
  41.                                  ":" + socketChannel.socket().getPort());
  42.               socketChannel.configureBlocking(false);
  43.               ByteBuffer buffer = ByteBuffer.allocate(1024);
  44.               socketChannel.register(selector,
  45.                                      SelectionKey.OP_READ |
  46.                                      SelectionKey.OP_WRITE, buffer);
  47.             }
  48.             if (key.isReadable()) {
  49.                 receive(key);
  50.             }
  51.             if (key.isWritable()) {
  52.                 send(key);
  53.             }
  54.         }catch(IOException e){
  55.            e.printStackTrace();
  56.            try{
  57.                if(key!=null){
  58.                    key.cancel();
  59.                    key.channel().close();
  60.                }
  61.            }catch(Exception ex){e.printStackTrace();}
  62.         }
  63.       }//#while
  64.     }//#while
  65.   }

  66.   public void send(SelectionKey key)throws IOException{
  67.     ByteBuffer buffer=(ByteBuffer)key.attachment();
  68.     SocketChannel socketChannel=(SocketChannel)key.channel();
  69.     buffer.flip();  //把极限设为位置,把位置设为0
  70.     String data=decode(buffer);
  71.     if(data.indexOf("\r\n")==-1)return;
  72.     String outputData=data.substring(0,data.indexOf("\n")+1);
  73.     System.out.print(outputData);
  74.     ByteBuffer outputBuffer=encode("echo:"+outputData);
  75.     while(outputBuffer.hasRemaining())
  76.       socketChannel.write(outputBuffer);

  77.     ByteBuffer temp=encode(outputData);
  78.     buffer.position(temp.limit());
  79.     buffer.compact();

  80.     if(outputData.equals("bye\r\n")){
  81.       key.cancel();
  82.       socketChannel.close();
  83.       System.out.println("关闭与客户的连接");
  84.     }
  85.   }

  86.   public void receive(SelectionKey key)throws IOException{
  87.     ByteBuffer buffer=(ByteBuffer)key.attachment();

  88.     SocketChannel socketChannel=(SocketChannel)key.channel();
  89.     ByteBuffer readBuff= ByteBuffer.allocate(32);
  90.     socketChannel.read(readBuff);
  91.     readBuff.flip();

  92.     buffer.limit(buffer.capacity());
  93.     buffer.put(readBuff);
  94.   }

  95.   public String decode(ByteBuffer buffer){  //解码
  96.     CharBuffer charBuffer= charset.decode(buffer);
  97.     return charBuffer.toString();
  98.   }
  99.   public ByteBuffer encode(String str){  //编码
  100.     return charset.encode(str);
  101.   }

  102.   public static void main(String args[])throws Exception{
  103.     EchoServer server = new EchoServer();
  104.     server.service();
  105.   }
  106. }





  107. /****************************************************
  108. * 作者:孙卫琴                                     *
  109. * 来源:<<Java网络编程精解>>                       *
  110. * 技术支持网址:www.javathinker.org                *
  111. ***************************************************/
复制代码
运行结果:
client:
触发可写监听
触发可写监听
触发可写监听
触发可写监听
触发可写监听
触发可写监听
触发可写监听
触发可写监听
触发可写监听
触发可写监听
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP