站長資訊網(wǎng)
        最全最豐富的資訊網(wǎng)站

        Java解讀NIO Socket非阻塞模式

        NIO
        有一個主要的類Selector,這個類似一個觀察者,只要我們把需要探知的socketchannel告訴Selector,我們接著做別的事情,當有
        事件發(fā)生時,他會通知我們,傳回一組SelectionKey,我們讀取這些Key,就會獲得我們剛剛注冊過的socketchannel,然后,我們從
        這個Channel中讀取數(shù)據(jù),放心,包準能夠讀到,接著我們可以處理這些數(shù)據(jù)。

          NIO主要原理和適用

          NIO 有一個主要的類Selector,這個類似一個觀察者,只要我們把需要探知的socketchannel告訴Selector,我們接著做別的事情,當有
          事件發(fā)生時,他會通知我們,傳回一組SelectionKey,我們讀取這些Key,就會獲得我們剛剛注冊過的socketchannel,然后,我們從
          這個Channel中讀取數(shù)據(jù),放心,包準能夠讀到,接著我們可以處理這些數(shù)據(jù)。

          Selector內(nèi)部原理實際是在做一個對所注冊的channel的輪詢訪問,不斷的輪詢(目前就這一個算法),一旦輪詢到一個channel有所注冊的事情發(fā)生,比如數(shù)據(jù)來了,他就會站起來報告,交出一把鑰匙,讓我們通過這把鑰匙來讀取這個channel的內(nèi)容。

          jdk供的無阻塞I/O(NIO)有效解決了多線程服務(wù)器存在的線程開銷問題,但在使用上略顯得復(fù)雜一些。在NIO中使用多線程,主要目的已不是為了應(yīng)對
          每個客戶端請求而分配獨立的服務(wù)線程,而是通過多線程充分使用用多個CPU的處理能力和處理中的等待時間,達到提高服務(wù)能力的目的。

          這段時間在研究NIO,寫篇博客來記住學過的東西。還是從最簡單的Hello
          World開始,client多線程請求server端,server接收client的名字,并返回Hello!
          +名字的字符格式給client。當然實際應(yīng)用并不這么簡單,實際可能是訪問文件或者數(shù)據(jù)庫獲取信息返回給client。非阻塞的NIO有何神秘之處?

          代 碼:

          1)server端代碼

                           
          1. public class HelloWorldServer {
          2. static int BLOCK = 1024;
          3. static String name = “”;
          4. protected Selector selector;
          5. protected ByteBuffer clientBuffer = ByteBuffer.allocate(BLOCK);
          6. protected CharsetDecoder decoder;
          7. static CharsetEncoder encoder = Charset.forName(“GB2312”).newEncoder();
          8. public HelloWorldServer(int port) throws IOException {
          9. selector = this.getSelector(port);
          10. Charset charset = Charset.forName(“GB2312”);
          11. decoder = charset.newDecoder();
          12. }
          13. // 獲取Selector
          14. protected Selector getSelector(int port) throws IOException {
          15. ServerSocketChannel server = ServerSocketChannel.open();
          16. Selector sel = Selector.open();
          17. server.socket().bind(new InetSocketAddress(port));
          18. server.configureBlocking(false);
          19. server.register(sel, SelectionKey.OP_ACCEPT);
          20. return sel;
          21. }
          22. // 監(jiān)聽端口
          23. public void listen() {
          24. try {
          25. for (;;) {
          26. selector.select();
          27. Iterator iter = selector.selectedKeys().iterator();
          28. while (iter.hasNext()) {
          29. SelectionKey key = (SelectionKey) iter.next();
          30. iter.remove();
          31. process(key);
          32. }
          33. }
          34. } catch (IOException e) {
          35. e.printStackTrace();
          36. }
          37. }
          38. // 處理事件
          39. protected void process(SelectionKey key) throws IOException {
          40. if (key.isAcceptable()) { // 接收請求
          41. ServerSocketChannel server = (ServerSocketChannel) key.channel();
          42. SocketChannel channel = server.accept();
          43. //設(shè)置非阻塞模式
          44. channel.configureBlocking(false);
          45. channel.register(selector, SelectionKey.OP_READ);
          46. } else if (key.isReadable()) { // 讀信息
          47. SocketChannel channel = (SocketChannel) key.channel();
          48. int count = channel.read(clientBuffer);
          49. if (count > 0) {
          50. clientBuffer.flip();
          51. CharBuffer charBuffer = decoder.decode(clientBuffer);
          52. name = charBuffer.toString();
          53. // System.out.println(name);
          54. SelectionKey sKey = channel.register(selector,
          55. SelectionKey.OP_WRITE);
          56. sKey.attach(name);
          57. } else {
          58. channel.close();
          59. }
          60. clientBuffer.clear();
          61. } else if (key.isWritable()) { // 寫事件
          62. SocketChannel channel = (SocketChannel) key.channel();
          63. String name = (String) key.attachment();
          64. ByteBuffer block = encoder.encode(CharBuffer
          65. .wrap(“Hello !” + name));
          66. channel.write(block);
          67. //channel.close();
          68. }
          69. }
          70. public static void main(String[] args) {
          71. int port = 8888;
          72. try {
          73. HelloWorldServer server = new HelloWorldServer(port);
          74. System.out.println(“listening on “ + port);
          75. server.listen();
          76. } catch (IOException e) {
          77. e.printStackTrace();
          78. }
          79. }
          80. }
           

          2)client端代碼

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   
          1. public class HelloWorldClient {
          2. static int SIZE = 10;
          3. static InetSocketAddress ip = new InetSocketAddress(“localhost”, 8888);
          4. static CharsetEncoder encoder = Charset.forName(“GB2312”).newEncoder();
          5. static class Message implements Runnable {
          6. protected String name;
          7. String msg = “”;
          8. public Message(String index) {
          9. this.name = index;
          10. }
          11. public void run() {
          12. try {
          13. long start = System.currentTimeMillis();
          14. //打開Socket通道
          15. SocketChannel client = SocketChannel.open();
          16. //設(shè)置為非阻塞模式
          17. client.configureBlocking(false);
          18. //打開選擇器
          19. Selector selector = Selector.open();
          20. //注冊連接服務(wù)端socket動作
          21. client.register(selector, SelectionKey.OP_CONNECT);
          22. //連接
          23. client.connect(ip);
          24. //分配內(nèi)存
          25. ByteBuffer buffer = ByteBuffer.allocate(8 * 1024);
          26. int total = 0;
          27. _FOR: for (;;) {
          28. selector.select();
          29. Iterator iter = selector.selectedKeys().iterator();
          30. while (iter.hasNext()) {
          31. SelectionKey key = (SelectionKey) iter.next();
          32. iter.remove();
          33. if (key.isConnectable()) {
          34. SocketChannel channel = (SocketChannel) key
          35. .channel();
          36. if (channel.isConnectionPending())
          37. channel.finishConnect();
          38. channel
          39. .write(encoder
          40. .encode(CharBuffer.wrap(name)));
          41. channel.register(selector, SelectionKey.OP_READ);
          42. } else if (key.isReadable()) {
          43. SocketChannel channel = (SocketChannel) key
          44. .channel();
          45. int count = channel.read(buffer);
          46. if (count > 0) {
          47. total += count;
          48. buffer.flip();
          49. while (buffer.remaining() > 0) {
          50. byte b = buffer.get();
          51. msg += (char) b;
          52. }
          53. buffer.clear();
          54. } else {
          55. client.close();
          56. break _FOR;
          57. }
          58. }
          59. }
          60. }
          61. double last = (System.currentTimeMillis() – start) * 1.0 / 1000;
          62. System.out.println(msg + “used time :” + last + “s.”);
          63. msg = “”;
          64. } catch (IOException e) {
          65. e.printStackTrace();
          66. }
          67. }
          68. }
          69. public static void main(String[] args) throws IOException {
          70. String names[] = new String[SIZE];
          71. for (int index = 0; index < SIZE; index++) {
          72. names[index] = “jeff[“ + index + “]”;
          73. new Thread(new Message(names[index])).start();
          74. }
          75. }
          76. }
           

          贊(0)
          分享到: 更多 (0)
          網(wǎng)站地圖   滬ICP備18035694號-2    滬公網(wǎng)安備31011702889846號
          主站蜘蛛池模板: 精品国产一区二区三区无码| 99精品国产自在现线观看| 真实国产乱子伦精品一区二区三区| 国产精品乱码高清在线观看| 午夜在线视频91精品| 国产精品欧美亚洲韩国日本久久| 国产午夜福利精品一区二区三区| 无码国模国产在线无码精品国产自在久国产 | 久久性精品| 亚洲精品电影网| 动漫精品专区一区二区三区不卡| 精品久久久久香蕉网| 人妻精品久久久久中文字幕69| 亚洲乱码日产精品a级毛片久久| 久久精品国产一区二区| mm1313亚洲国产精品无码试看| 999国内精品永久免费视频| 久久国产亚洲精品无码| 久久久精品2019免费观看| 中文字幕久久精品| 中国国产精品| 亚洲国产成人精品女人久久久 | 国产叼嘿久久精品久久| 桃花岛精品亚洲国产成人| 久久91精品久久91综合| 国内精品免费视频精选在线观看| 99精品国产一区二区三区| 国产成人精品视频一区二区不卡 | 国产亚洲精品岁国产微拍精品| 久久久久亚洲精品无码蜜桃| 日韩精品无码一区二区三区| 亚洲AV日韩精品久久久久久久| 亚洲精品无码鲁网中文电影| 亚洲韩国精品无码一区二区三区 | 一本之道av不卡精品| 午夜肉伦伦影院久久精品免费看国产一区二区三区 | 国产精品性爱| 精品久久久久久久中文字幕 | 国产精品岛国久久久久| 九九热精品在线| 99久久精品国产一区二区|