java nio Socket非阻塞模式

來源:互聯網
上載者:User

NIO 有一個主要的類Selector,這個類似一個觀察者,只要我們把需要探知的socketchannel告訴Selector,我們接著做別的事情,當有 事件發生時,他會通知我們,傳回一組SelectionKey,我們讀取這些Key,就會獲得我們剛剛註冊過的socketchannel,然後,我們從 這個Channel中讀取資料,放心,包準能夠讀到,接著我們可以處理這些資料。
Selector內部原理實際是在做一個對所註冊的channel的輪詢訪問,不斷的輪詢(目前就這一個演算法),一旦輪詢到一個channel有所註冊的事情發生,比如資料來了,他就會站起來報告,交出一把鑰匙,讓我們通過這把鑰匙來讀取這個channel的內容。
jdk供的無阻塞I/O(NIO)有效解決了多線程伺服器存在的線程開銷問題,但在使用上略顯得複雜一些。在NIO中使用多線程,主要目的已不是為了應對 每個用戶端請求而分配獨立的服務線程,而是通過多線程充分使用用多個CPU的處理能力和處理中的等待時間,達到提高服務能力的目的。

server端代碼:

public class HelloWorldServer {        static int BLOCK = 1024;       static String name = "";       protected Selector selector;       protected ByteBuffer clientBuffer = ByteBuffer.allocate(BLOCK);       protected CharsetDecoder decoder;       static CharsetEncoder encoder = Charset.forName("GB2312").newEncoder();        public HelloWorldServer(int port) throws IOException {           selector = this.getSelector(port);           Charset charset = Charset.forName("GB2312");           decoder = charset.newDecoder();       }        // 擷取Selector       protected Selector getSelector(int port) throws IOException {           ServerSocketChannel server = ServerSocketChannel.open();           Selector sel = Selector.open();           server.socket().bind(new InetSocketAddress(port));           server.configureBlocking(false);           server.register(sel, SelectionKey.OP_ACCEPT);           return sel;       }        // 監聽連接埠       public void listen() {           try {               for (;;) {                   selector.select();                   Iterator iter = selector.selectedKeys().iterator();                   while (iter.hasNext()) {                       SelectionKey key = (SelectionKey) iter.next();                       iter.remove();                       process(key);                   }               }           } catch (IOException e) {               e.printStackTrace();           }       }        // 處理事件       protected void process(SelectionKey key) throws IOException {           if (key.isAcceptable()) { // 接收請求               ServerSocketChannel server = (ServerSocketChannel) key.channel();               SocketChannel channel = server.accept();               //設定非阻塞模式               channel.configureBlocking(false);               channel.register(selector, SelectionKey.OP_READ);           } else if (key.isReadable()) { // 讀資訊               SocketChannel channel = (SocketChannel) key.channel();               int count = channel.read(clientBuffer);               if (count > 0) {                   clientBuffer.flip();                   CharBuffer charBuffer = decoder.decode(clientBuffer);                   name = charBuffer.toString();                   // System.out.println(name);                   SelectionKey sKey = channel.register(selector,                           SelectionKey.OP_WRITE);                   sKey.attach(name);               } else {                   channel.close();               }                clientBuffer.clear();           } else if (key.isWritable()) { // 寫事件               SocketChannel channel = (SocketChannel) key.channel();               String name = (String) key.attachment();                              ByteBuffer block = encoder.encode(CharBuffer                       .wrap("Hello !" + name));                               channel.write(block);                //channel.close();            }       }        public static void main(String[] args) {           int port = 8888;           try {               HelloWorldServer server = new HelloWorldServer(port);               System.out.println("listening on " + port);                              server.listen();                          } catch (IOException e) {               e.printStackTrace();           }       }   }  

client端代碼:

public class HelloWorldClient {        static int SIZE = 10;       static InetSocketAddress ip = new InetSocketAddress("localhost", 8888);       static CharsetEncoder encoder = Charset.forName("GB2312").newEncoder();        static class Message implements Runnable {           protected String name;           String msg = "";            public Message(String index) {               this.name = index;           }            public void run() {               try {                   long start = System.currentTimeMillis();                   //開啟Socket通道                   SocketChannel client = SocketChannel.open();                   //設定為非阻塞模式                   client.configureBlocking(false);                   //開啟選取器                   Selector selector = Selector.open();                   //註冊串連服務端socket動作                   client.register(selector, SelectionKey.OP_CONNECT);                   //串連                   client.connect(ip);                   //分配記憶體                   ByteBuffer buffer = ByteBuffer.allocate(8 * 1024);                   int total = 0;                    _FOR: for (;;) {                       selector.select();                       Iterator iter = selector.selectedKeys().iterator();                        while (iter.hasNext()) {                           SelectionKey key = (SelectionKey) iter.next();                           iter.remove();                           if (key.isConnectable()) {                               SocketChannel channel = (SocketChannel) key                                       .channel();                               if (channel.isConnectionPending())                                   channel.finishConnect();                               channel                                       .write(encoder                                               .encode(CharBuffer.wrap(name)));                                channel.register(selector, SelectionKey.OP_READ);                           } else if (key.isReadable()) {                               SocketChannel channel = (SocketChannel) key                                       .channel();                               int count = channel.read(buffer);                               if (count > 0) {                                   total += count;                                   buffer.flip();                                    while (buffer.remaining() > 0) {                                       byte b = buffer.get();                                       msg += (char) b;                                                                          }                                    buffer.clear();                               } else {                                   client.close();                                   break _FOR;                               }                           }                       }                   }                   double last = (System.currentTimeMillis() - start) * 1.0 / 1000;                   System.out.println(msg + "used time :" + last + "s.");                   msg = "";               } catch (IOException e) {                   e.printStackTrace();               }           }       }        public static void main(String[] args) throws IOException {                  String names[] = new String[SIZE];            for (int index = 0; index < SIZE; index++) {               names[index] = "jeff[" + index + "]";               new Thread(new Message(names[index])).start();           }              }   }  

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.