如果从selector里面接到readable key以后,读完了以后直接写出去还不将它改成writable这样好吗?
比如:public void read(SelectionKey key) throws IOException {
        SocketChannel clntChan = (SocketChannel) key.channel();
        ByteBuffer buffer = ByteBuffer.allocate(128);
        clntChan.read(buffer);
        
        buffer.flip();
        clntChan.write(buffer);
    }
这样直接把信息echo回去,而不通过把它改成writable,所以整个过程不判断有没有writable的key。如果要是发给指定channel的话可以直接从一个collection里面调出这个channel然后写出去,请问这样做法的利弊。javanio

解决方案 »

  1.   

    clntChan.write(buffer)返回一个int,是已经被写入的字节数,可能少于buffer里的字节数(当channel来不及发送的时候)。nio的完美处理比想象的要难很多
      

  2.   

    1. 一个selector专门侦听Writable,不断从一个缓存队列里拿bytebuffer出来写
    2. read这个selector先检查缓存队列中是否有bytebuffer,如果有,将当前要写的加入队列末尾,如果没有,直接调用channel.write,并查看返回值,如果等于buffer.remaining(要在write之前取这个值),表示完全写入,否则加入队列
    3. 整个过程要加锁
      

  3.   

    能给点代码吗有点不明白
    1是要用两个selector一个write一个read吗
    2什么是队列中有butebuffer?
      

  4.   

    可以用一个selector同时read和write其实队列就是Queue<ByteBuffer>,在你read之后,先看queue是否是空,如果是空,就直接调用socket.write,否则queue.offer(buffer.clone())。在writable的时候,就看queue.size()是否为0,如果不是就buffer = queue.poll(),然后socket.write(buffer)。当然是假设你的selector只注册了一个channel的情况。多个channel的话要复杂一些,不过无非就是一个Map<Channel, Queue<ByteBuffer>>了
      

  5.   


    这样会造成read进来的一个buffer分两次write出去吗?如果这样的话接受的client那边还要在接受的完整性上做处理?
      

  6.   

    很有可能会分两次write。read这边完整性判断即使你write这边不这样写(直接用Socket的blocking模式)也是需要做的,虽然99.9%的情况下没有问题,而且在Localhost对传的情况下这个比率还会更高,但是这不是一个严密的逻辑。