nio 写事件

selector.select()
会阻塞等待4中事件发生
/**
  * Operation-set bit for read operations.
  *
  * <p> Suppose that a selection key's interest set contains
  * <tt>OP_READ</tt> at the start of a <a
  * href="Selector.html#selop">selection operation</a>.  If the selector
  * detects that the corresponding channel is ready for reading, has reached
  * end-of-stream, has been remotely shut down for further reading, or has
  * an error pending, then it will add <tt>OP_READ</tt> to the key's
  * ready-operation set and add the key to its selected-key&nbsp;set.  </p>
  */
 public static final int OP_READ = 1 << 0;

 /**
  * Operation-set bit for write operations.
  *
  * <p> Suppose that a selection key's interest set contains
  * <tt>OP_WRITE</tt> at the start of a <a
  * href="Selector.html#selop">selection operation</a>.  If the selector
  * detects that the corresponding channel is ready for writing, has been
  * remotely shut down for further writing, or has an error pending, then it
  * will add <tt>OP_WRITE</tt> to the key's ready set and add the key to its
  * selected-key&nbsp;set.  </p>
  */
 public static final int OP_WRITE = 1 << 2;

 /**
  * Operation-set bit for socket-connect operations.
  *
  * <p> Suppose that a selection key's interest set contains
  * <tt>OP_CONNECT</tt> at the start of a <a
  * href="Selector.html#selop">selection operation</a>.  If the selector
  * detects that the corresponding socket channel is ready to complete its
  * connection sequence, or has an error pending, then it will add
  * <tt>OP_CONNECT</tt> to the key's ready set and add the key to its
  * selected-key&nbsp;set.  </p>
  */
 public static final int OP_CONNECT = 1 << 3;

 /**
  * Operation-set bit for socket-accept operations.
  *
  * <p> Suppose that a selection key's interest set contains
  * <tt>OP_ACCEPT</tt> at the start of a <a
  * href="Selector.html#selop">selection operation</a>.  If the selector
  * detects that the corresponding server-socket channel is ready to accept
  * another connection, or has an error pending, then it will add
  * <tt>OP_ACCEPT</tt> to the key's ready set and add the key to its
  * selected-key&nbsp;set.  </p>
  */
 public static final int OP_ACCEPT = 1 << 4;

读事件
写事件
connect事件
accept事件

写事件是比较特殊的一种,因为channel一般情况下都是可写的,所以我们如果注册写事件,然后select()方法看到channel可写,就不会阻塞,最后走到key.isWritable判断为true,然后一直循环

while(true){
     selector.select()
     val iterator = selector.selectedKeys().iterator()

     while (iterator.hasNext()) {
         val key = iterator.next()
         
         iterator.remove()
         if (key.isWritable){
             
         }
     }
 }

netty中的用法是这样的

 @Override
 protected void doWrite(ChannelOutboundBuffer in) throws Exception {
 	 //获取循环写N次,设置写N次的原因是当循环发送,线程就会不断尝试写操作,此时线程就无法处理其他请求,如果网络状况不好或者对方接收太慢,可能会导致线程假死
     int writeSpinCount = config().getWriteSpinCount();
     do {
     	 //从上次位置开始
         Object msg = in.current();
         if (msg == null) {
             // 写完了,清理write操作位
             clearOpWrite();
             return;
         }
         //doWriteInternal中 会记录发送了多少数据,这样当IO复用器再次轮询就可以继续发送剩余的数据
         writeSpinCount -= doWriteInternal(in, msg);
     } while (writeSpinCount > 0);

	 //写N次之后没写完,设置write操作位,这样线程可以处理其他事件
     incompleteWrite(writeSpinCount < 0);
 }




protected final void incompleteWrite(boolean setOpWrite) {
    
    if (setOpWrite) {
        //设置write标志位,这样IO复用器就会不断轮询对应channel 来处理未发送的半包
        setOpWrite();
    } else {
       //如果不设置标志位,则新建一个任务放入线程池
        clearOpWrite();
		eventLoop().execute(flushTask);
    }
}
发布了44 篇原创文章 · 获赞 13 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/qq_19457117/article/details/84074082
NIO
今日推荐