nio,一般的reactor,Mina的Reactor

來源:互聯網
上載者:User

nio:

    一個簡單的nioserver。啟動後,在瀏覽器輸入:http://localhost:1234。就可以看到http的請求。

public class Test<T> implements Callable<T> {private Selector selector;// 建立全域selectorpublic Test() throws IOException {selector = Selector.open();ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();serverSocketChannel.configureBlocking(false);serverSocketChannel.socket().bind(new InetSocketAddress(1234));serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);}public T call() throws Exception {for (;;) {if (selector.select(1000) == 0) {continue;}Iterator<SelectionKey> keyIterator = selector.selectedKeys().iterator();while (keyIterator.hasNext()) {SelectionKey key = keyIterator.next();if (key.isAcceptable()) {SocketChannel clientChannel = ((ServerSocketChannel) key.channel()).accept();clientChannel.configureBlocking(false);clientChannel.register(key.selector(), SelectionKey.OP_READ);}if (key.isReadable()) {// 獲得與用戶端通訊的通道SocketChannel clientChannel = (SocketChannel) key.channel();// 得到並重設緩衝區的主要索引值ByteBuffer buffer = (ByteBuffer) key.attachment();buffer.clear();// 讀取資訊獲得讀取的位元組數long bytesRead = clientChannel.read(buffer);if (bytesRead == -1) {// 沒有讀取到內容的情況clientChannel.close();} else {// 將緩衝區準備為資料傳出狀態buffer.flip();// 將獲得位元組字串(使用Charset進行解碼)String receivedString = Charset.forName("utf-8").newDecoder().decode(buffer).toString();// 控制台列印出來System.out.println("接收到資訊:" + receivedString);// 準備發送的文本String sendString = "你好,用戶端. 已經收到你的資訊" + receivedString;// 將要發送的字串編碼(使用Charset進行編碼)後再進行封裝buffer = ByteBuffer.wrap(sendString.getBytes("utf-8"));// 發送回去clientChannel.write(buffer);// 設定為下一次讀取或是寫入做準備key.interestOps(SelectionKey.OP_READ| SelectionKey.OP_WRITE);}}keyIterator.remove();}}}public static void main(String args[]) throws IOException, Exception {new Test().call();}}

Reactor模式:

     1.Reactor 負責響應IO事件,一旦發生,廣播發送給相應的Handler去處理。
   2.Handler 是負責非堵塞行為。

public class Reactor implements Runnable{final Selector selector;final ServerSocketChannel serverSocket;ExecutorService pool = Executors.newFixedThreadPool(3);public Reactor(int port) throws IOException {selector = Selector.open();serverSocket = ServerSocketChannel.open();InetSocketAddress address = new InetSocketAddress(port);serverSocket.socket().bind(address);serverSocket.configureBlocking(false);// 向selector註冊該channelSelectionKey sk = serverSocket.register(selector,SelectionKey.OP_ACCEPT);// 利用sk的attache功能綁定Acceptor 如果有事情,觸發Acceptorsk.attach(new Acceptor());}void dispatch(SelectionKey k) {Runnable r = (Runnable) (k.attachment());r.run();}public void run() {try {while (true) {int temp = selector.select();Iterator<SelectionKey> keyIter = selector.selectedKeys().iterator();while (keyIter.hasNext()) {SelectionKey key = keyIter.next();keyIter.remove();dispatch(key);}}} catch (IOException e) {e.printStackTrace();}}class Acceptor implements Runnable {public void run() {try {SocketChannel c = serverSocket.accept();if (c != null)pool.execute(new SocketReadHandler(selector, c));} catch (IOException e) {e.printStackTrace();}}}public static void main(String args[]) throws IOException {new Reactor(1234).run();}}

public class SocketReadHandler implements Runnable {public static Logger logger = Logger.getLogger("SocketReadHandler");final SocketChannel sc;final SelectionKey sk;ByteBuffer input = ByteBuffer.allocate(1024);ByteBuffer output = ByteBuffer.allocate(1024);static final int READING = 0, SENDING = 1;int state = READING;public SocketReadHandler(Selector sel, SocketChannel sc) throws IOException {this.sc = sc;sc.configureBlocking(false);sk = sc.register(sel, 0);// 將SelectionKey綁定為本Handler 下一步有事件觸發時,將調用本類的run方法。// 參看dispatch(SelectionKey k)sk.attach(this);// 同時將SelectionKey標記為可讀,以便讀取。sk.interestOps(SelectionKey.OP_READ);sel.wakeup();}public void run() {try {if (state == READING) {read();} else if (state == SENDING) {send();}} catch (IOException e) {e.printStackTrace();}}private void send() throws IOException {sc.write(output);sk.cancel();}private void read() throws IOException {long bytesRead = sc.read(input);if (bytesRead == -1) {sc.close();} else {input.flip();String receivedString = Charset.forName("utf-8").newDecoder().decode(input).toString();// 控制台列印出來System.out.println("接收到資訊:" + receivedString);state = SENDING;sk.interestOps(SelectionKey.OP_WRITE);}}}


      上面代碼改編自《Reactor模式和NIO》,詳見參考資料。

      SocketChannel的attach功能,將Hanlder和可能會發生事件的channel連結在一起,當發生事件時,可以立即觸發相應連結的Handler。增加了一個線程池

Mina的Reator:

     

    與傳統的單個Reactor模式實現不同,mina中採用了Multiple Reactor的方式。NioSocketAcceptor和NioProcessor使用不同selector,能夠更加充分的榨取伺服器的效能。 

acctptor主要負責 
1. 綁定一個/多個連接埠,開始監聽 
2. 處理用戶端的建鏈請求 
3. 關閉一個/多個監聽連接埠 
processor主要負責 
1. 接受用戶端發送的資料,並轉寄給商務邏輯成處理 
2. 發送資料到用戶端 

   mina的reactor模式詳見mina1.0.10的源碼:http://mina.apache.org/dyn/closer.cgi/mina/1.0.10/mina-1.0.10.zip





參考資料:

uniseraph:http://uniseraph.iteye.com/blog/228221——《【mina指南】mina中的reactor模式(一)》

uniseraph:http://uniseraph.iteye.com/blog/229130——《【mina指南】mina中的reactor模式(二)》

何楊:http://www.blogjava.net/heyang/archive/2011/01/03/342193.html——《Java
NIO 伺服器端簡單實現例子》

板橋裡人:http://www.jdon.com/concurrent/reactor.htm——《Reactor模式和NIO》

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.