java Selector 备忘

Thinking in Enterprise Java 里的例子

//: TIEJ:X1:NonBlockingIO.java
// Socket and selector configuration for non-blocking
// Connects to JabberServer.java
// {RunByHand}
import java.net.*;
import java.nio.channels.*;
import java.util.*;
import java.io.*;
/**
 * Aim: Shows how to use selector. No reading/writing
 *      just shows the readiness of operations.
 *
 * PseudoCode:
 * -> Create a selector.
 * -> Create a channel
 * -> Bind the socket associated with this channel to a
 *    <client-port>
 * -> Configure the channel as non-blocking
 * -> Register the channel with selector.
 * -> Invoke select() so that it blocks until registered
 *    channel is ready. (as opposed to select(long timeout)
 * -> Get the set of keys whose underlying channel is ready
 *    for the operation they showed interest when they
 *    registered with the selector.
 * -> Iterate through the keys.
 * -> For every key check if the underlying channel is ready
 *    for the operation it is interested in.
 * -> If ready print message of readiness.
 *
 * Notes:
 * -> Need MultiJabberServer running on the local machine.
 *    You run it to connect to the local MultiJabberServer
 * -> It causes and exception at MultiJabberServer but
 *    this exception is expected.
 */
public class NonBlockingIO {
  public static void main(String[] args)
    throws IOException {
    if(args.length < 2) {
      System.out.println(
        "Usage: java <client port> <local server port>");
      System.exit(1);
    }
    int cPort = Integer.parseInt(args[0]);
    int sPort = Integer.parseInt(args[1]);
    SocketChannel ch = SocketChannel.open();
    Selector sel = sel = Selector.open();
    try {
      ch.socket().bind(new InetSocketAddress(cPort));
      ch.configureBlocking(false);
      // channel interested in performing read/write/connect
      ch.register(sel, SelectionKey.OP_READ
        | SelectionKey.OP_WRITE | SelectionKey.OP_CONNECT);
      // Unblocks when ready to read/write/connect
      sel.select();
      // Keys whose underlying channel is ready, the
      // operation this channel is interested in can be
      // performed without blocking.
      Iterator it = sel.selectedKeys().iterator();
      while(it.hasNext()) {
        SelectionKey key = (SelectionKey)it.next();
        it.remove();
        // Is underlying channel of key ready to connect?
     // if((key.readyOps() & SelectionKey.OP_CONNECT) != 0) {
        if(key.isConnectable()) {
          InetAddress ad = InetAddress.getLocalHost();
          System.out.println("Connect will not block");
          //You must check the return value of connect to make
          //sure that it has connected. This call being
          //non-blocking may return without connecting when
          //there is no server where you are trying to connect
          //Hence you call finishConnect() that finishes the
          //connect operation.
          if(!ch.connect(new InetSocketAddress(ad, sPort)))
            ch.finishConnect();
        }
        // Is underlying channel of key ready to read?
        // if((key.readyOps() & SelectionKey.OP_READ) != 0)
        if(key.isReadable())
          System.out.println("Read will not block");
        // Is underlying channel of key ready to write?
        // if((key.readyOps() & SelectionKey.OP_WRITE) != 0)
        if(key.isWritable())
          System.out.println("Write will not block");
      }
    } finally {
      ch.close();
      sel.close();
    }
  }
} ///:~
//: TIEJ:X1:JabberClient1.java
// Very simple client that just sends lines to the server
// and reads lines that the server sends.
// {RunByHand}
import java.net.*;
import java.util.*;
import java.io.*;
import java.nio.*;
import java.nio.channels.*;
import java.nio.charset.*;

public class JabberClient1 {
  public static void main(String[] args)
      throws IOException {
    if(args.length < 1) {
      System.out.println(
        "Usage: java JabberClient1 <client-port>");
      System.exit(1);
    }
    int clPrt = Integer.parseInt(args[0]);
    SocketChannel sc = SocketChannel.open();
    Selector sel = Selector.open();
    try {
      sc.configureBlocking(false);
      sc.socket().bind(new InetSocketAddress(clPrt));
      sc.register(sel, SelectionKey.OP_READ |
        SelectionKey.OP_WRITE  | SelectionKey.OP_CONNECT);
      int i = 0;
      // Because of the asynchronous nature you do not know
      // when reading and writing is done, hence you need to
      // keep track of this, boolean written is used to
      // alternate between read and write. Whatever is written
      // is echoed and should be read.
      // boolean done is used to check when to break out of
      // the loop
      boolean written = false, done = false;
      //JabberServer.java to which this client connects writes
      //using BufferedWriter.println(). This method performs
      //encoding according to the defualt charset
      String encoding = System.getProperty("file.encoding");
      Charset cs = Charset.forName(encoding);
      ByteBuffer buf = ByteBuffer.allocate(16);
      while(!done) {
        sel.select();
        Iterator it = sel.selectedKeys().iterator();
        while(it.hasNext()) {
          SelectionKey key = (SelectionKey)it.next();
          it.remove();
          sc = (SocketChannel)key.channel();
          if(key.isConnectable() && !sc.isConnected()) {
            InetAddress addr = InetAddress.getByName(null);
            boolean success = sc.connect(
              new InetSocketAddress(addr,
                JabberServer.PORT));
            if(!success) sc.finishConnect();
          }
          if(key.isReadable() && written) {
            if(sc.read((ByteBuffer)buf.clear()) > 0) {
              written = false;
              String response = cs.decode(
                (ByteBuffer) buf.flip()).toString();
              System.out.print(response);
              if(response.indexOf("END") != -1) done = true;
            }
          }
          if(key.isWritable() && !written) {
            if(i < 10) sc.write(ByteBuffer.wrap(
                new String("howdy "+ i + '\n').getBytes()));
            else if(i == 10) sc.write(ByteBuffer.wrap(
                new String("END\n").getBytes()));
            written = true;
            i++;
          }
        }
      }
    } finally {
      sc.close();
      sel.close();
    }
  }
} ///:~
//: TIEJ:X1:MultiJabberServer1.java
// Has the same semantics as multi-threaded
// MultiJabberServer
// {RunByHand}
import java.io.*;
import java.net.*;
import java.nio.*;
import java.nio.channels.*;
import java.nio.charset.*;
import java.util.*;
/**
 * The Server accepts connections in non-blocking fashion.
 * A connection when established, a socket is created,
 * which is registered for read/write with the selector.
 * Reading/Writing is performed on this socket when the
 * selector unblocks.
 * This program works exactly the same way as MultiJabberServer.
 */
public class MultiJabberServer1 {
  public static final int PORT = 8080;
  public static void main(String[] args)
      throws IOException {
    //Channel read from data will be in ByteBuffer form
    //written by PrintWriter.println(). Decoding of this
    //byte stream requires character set of default encoding.
    String encoding = System.getProperty("file.encoding");
    //Had to initialized here since we do not wish to create
    //a new instance of Charset everytime it is required
    //Charset cs = Charset.forName(
    //  System.getProperty("file.encoding"));
    Charset cs = Charset.forName(encoding);
    ByteBuffer buffer = ByteBuffer.allocate(16);
    SocketChannel ch = null;
    ServerSocketChannel ssc = ServerSocketChannel.open();
    Selector sel = Selector.open();
    try {
      ssc.configureBlocking(false);
      //Local address on which it will listen for connections
      //Note: Socket.getChannel() returns null unless a channel
      //is associated with it as shown below.
      //i.e the expression (ssc.socket().getChannel() != null) is true
      ssc.socket().bind(new InetSocketAddress(PORT));
      // Channel is interested in OP_ACCEPT events
      SelectionKey key =
        ssc.register(sel, SelectionKey.OP_ACCEPT);
      System.out.println("Server on port: " + PORT);
      while(true) {
        sel.select();
        Iterator it = sel.selectedKeys().iterator();
        while(it.hasNext()) {
          SelectionKey skey = (SelectionKey)it.next();
          it.remove();
          if(skey.isAcceptable()) {
            ch = ssc.accept();
            System.out.println(
              "Accepted connection from:" + ch.socket());
            ch.configureBlocking(false);
            ch.register(sel, SelectionKey.OP_READ);
          } else {
            // Note no check performed if the channel
            // is writable or readable - to keep it simple
            ch = (SocketChannel)skey.channel();
            ch.read(buffer);
            CharBuffer cb = cs.decode(
              (ByteBuffer)buffer.flip());
            String response = cb.toString();
            System.out.print("Echoing : " + response);
            ch.write((ByteBuffer)buffer.rewind());
            if(response.indexOf("END") != -1) ch.close();
            buffer.clear();
          }
        }
      }
    } finally {
      if(ch != null) ch.close();
      ssc.close();
      sel.close();
    }
  }
} ///:~
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值