2014-02-20 4 views
0

Я написал простой эхо-клиент и селектор каждый раз, когда выбирает SocketChannel как читаемый. У меня EOF, если я попытаюсь прочитать этот socketChannel.SelectedKeys не удаляет socketChannel и Selector выбирает его каждый раз

Я удалил SelectedKey из selector.selectedKeys(). В чем проблема с селектором?

import java.io.IOException; 
import java.net.InetSocketAddress; 
import java.nio.ByteBuffer; 
import java.nio.channels.SelectionKey; 
import java.nio.channels.Selector; 
import java.nio.channels.SocketChannel; 
import java.nio.charset.Charset; 
import java.util.Iterator; 

public class Test { 
    public static void main(String[] args) { 
     try { 
      Selector selector = Selector.open(); 

      SocketChannel socketChannel = SocketChannel.open(); 
      socketChannel.configureBlocking(false); 

      socketChannel.register(selector, SelectionKey.OP_CONNECT | SelectionKey.OP_WRITE | SelectionKey.OP_READ); 
      socketChannel.connect(new InetSocketAddress("localhost", 2000)); 

      System.out.println("start eventloop"); 

      ByteBuffer byteBuffer = ByteBuffer.wrap("echo\n".getBytes()); 
      int i = 0; 
      while(true) { 
       try{ 
        if(i++==10) break; 
        selector.select(); 
        System.out.println("events: " + selector.selectedKeys().size()); 
        Iterator<SelectionKey> it = selector.selectedKeys().iterator(); 

        while(it.hasNext()) { 
         SelectionKey selectionKey = it.next(); 
         SocketChannel channel = (SocketChannel)selectionKey.channel(); 

         if(selectionKey.isConnectable()) { 
          System.out.println("connectable"); 
          try{ 
           channel.finishConnect(); 
           System.out.println("connected " + channel.getLocalAddress() + " <> " + channel.getRemoteAddress()); 
          } catch (Exception e) { 
           e.printStackTrace(); 
           channel.close(); 
          } 
         } 
         if(selectionKey.isReadable()) { 
          System.out.println("readable"); 
          ByteBuffer buffer = ByteBuffer.allocate(32); 
          buffer.clear(); 
          int x = channel.read(buffer); 
          if(x > 0) { 
           buffer.flip(); 
           System.out.println("server> " + Charset.defaultCharset().decode(buffer).toString()); 
          } else { 
           System.out.println("EOF"); 
          } 
         } 
         if(selectionKey.isWritable()) { 
          System.out.println("writeable"); 
          channel.write(byteBuffer); 
          byteBuffer.flip(); 
          channel.register(selector, SelectionKey.OP_READ); 
         } 
         it.remove(); 
        } 
        System.out.println("not handled events:" + selector.selectedKeys().size()); 
       } catch (Exception e) { 
        e.printStackTrace(); 
        break; 
       } 
      } 
      selector.close(); 
      socketChannel.close(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 
} 

STDOUT:

start eventloop 
events: 1 
connectable 
connected /127.0.0.1:65283 <> localhost/127.0.0.1:2000 
not handled events:0 
events: 1 
writeable 
not handled events:0 
events: 1 
readable 
server> echo 

not handled events:0 
events: 1 
readable 
EOF 
not handled events:0 
events: 1 
readable 
EOF 
not handled events:0 
events: 1 
readable 
EOF 
not handled events:0 
events: 1 
readable 
EOF 
not handled events:0 
events: 1 
readable 
EOF 
not handled events:0 
events: 1 
readable 
EOF 
not handled events:0 
events: 1 
readable 
EOF 
not handled events:0 

ответ

0

Это удалить его, но он просто держит появляясь, потому что OP_WRITE почти всегда готов, потому что буфер передачи сокета почти всегда есть место в нем. Вы должны регистрироваться только для этого события, когда вы столкнулись с записью нулевой длины, и вам следует отменить регистрацию, как только будет выполнена запись, запрошенная OP_WRITE.

Смежные вопросы