溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

怎么用nio實現(xiàn)Echo服務

發(fā)布時間:2021-07-21 21:30:10 來源:億速云 閱讀:104 作者:chen 欄目:編程語言

這篇文章主要介紹“怎么用nio實現(xiàn)Echo服務”,在日常操作中,相信很多人在怎么用nio實現(xiàn)Echo服務問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”怎么用nio實現(xiàn)Echo服務”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!

今天突然間想用nio實現(xiàn)個Echo服務,程序?qū)崿F(xiàn)起來實現(xiàn)不算困難,但跑起來后,在Server端的ServerSocket完成accept之后,我的CPU總是跳到100%。嗯,小郁悶,后來,才發(fā)現(xiàn)自己在Server端注冊了多余的監(jiān)聽事件SelectionKey.OP_WRITE,改過來后好多了,希望記住這個教訓。

EchoServer.java

package edu.dlut.zxf.nio;   import java.io.IOException;  import java.net.InetAddress;  import java.net.InetSocketAddress;  import java.nio.ByteBuffer;  import java.nio.channels.SelectionKey;  import java.nio.channels.Selector;  import java.nio.channels.ServerSocketChannel;  import java.nio.channels.SocketChannel;  import java.util.Set;   /**   * Echo服務器   * @author finux   */ public class EchoServer {      public final static int BUFFER_SIZE = 1024; //默認端口      public final static String HOST = "210.30.107.17";      public final static int PORT = 8888;            public static void main(String[] args) {          ServerSocketChannel ssc = null;          //緩沖區(qū)          ByteBuffer buffer = ByteBuffer.allocate(BUFFER_SIZE);          Selector selector = null;          try {              selector = Selector.open();              ssc = ServerSocketChannel.open();              ssc.socket().bind(new InetSocketAddress(InetAddress.getByName(HOST), PORT));              ssc.configureBlocking(false);              ssc.register(selector, SelectionKey.OP_ACCEPT);                   print("服務器啟動,準備好連接...");              while (selector.select() > 0) {                       Set<SelectionKey> selectionKeys = selector.selectedKeys();                  for (SelectionKey key: selectionKeys) {                      if (key.isAcceptable()) {                          SocketChannel sc = ssc.accept();                          print("有新的連接!地址:" + sc.socket().getRemoteSocketAddress());                          sc.configureBlocking(false);                          sc.register(selector, SelectionKey.OP_READ);                          // 不要寫成:                          // sc.register(selector, SelectionKey.OP_READ | SelectionKey.OP_WRITE);                          // 畢竟這樣多注冊的無用的事件SelectionKey.OP_WRTE                          // 如果是這樣,在完成accept后,CPU也許會跑到100%                                                }                      //same to if ((ops & SelectionKey.OP_READ) == SelectionKey.OP_READ) {                      if (key.isReadable()) {                           SocketChannel sc = (SocketChannel)key.channel();                          print("有新的讀??!地址:" + sc.socket().getRemoteSocketAddress());                                                buffer.clear();                                               sc.read(buffer);                          buffer.flip();                          byte[] b = new byte[buffer.limit()];                          buffer.get(b);                          String s = new String(b);                          if (s.equals("bye")) {                              print("斷開連接:" + sc.socket().getRemoteSocketAddress());                                //斷開連接后,取消此鍵的通道到其選擇器的注冊                              key.cancel();                              sc.close();                              continue;                          }                          print("讀取的內(nèi)容為:" + s);                             buffer.clear();                          s = "echo: " + s;                          buffer.put(s.getBytes());                          buffer.flip();                          sc.write(buffer);                      }                   }                  selectionKeys.clear();              }          } catch(IOException e) {              e.printStackTrace();          }       }            private static void print(String s) {          System.out.println(s);      }  }

EchoClient.java

package edu.dlut.zxf.nio;   import java.util.Set;  import java.io.BufferedReader;  import java.io.IOException;  import java.io.InputStreamReader;  import java.net.InetSocketAddress;  import java.net.InetAddress;  import java.nio.ByteBuffer;  import java.nio.channels.SelectionKey;  import java.nio.channels.Selector;  import java.nio.channels.SocketChannel;   /**   * Echo客戶端   * @author finux   */ public class EchoClient {      public static void main(String[] args) {          ByteBuffer buffer = ByteBuffer.allocate(EchoServer.BUFFER_SIZE);          Selector selector = null;          SocketChannel sc = null;          try {              selector = Selector.open();              sc = SocketChannel.open();              sc.configureBlocking(false);              sc.connect(new InetSocketAddress(InetAddress.getByName(EchoServer.HOST), EchoServer.PORT));              print("客戶端啟動,準備連接...");              if (sc.isConnectionPending()) {                  sc.finishConnect();              }              print("完成連接");              sc.register(selector, SelectionKey.OP_READ | SelectionKey.OP_WRITE);                            boolean writed = false;              boolean down = false;              while (!down && selector.select() > 0) {                                  Set<SelectionKey> selectionKeys = selector.selectedKeys();                  for (SelectionKey key: selectionKeys) {                                       //int ops = key.readyOps();                      //if ((ops & SelectionKey.OP_WRITE) == SelectionKey.OP_WRITE && !writed) {                      if (key.isWritable() && !writed) {                          System.out.print("Input(bye to end): ");                          BufferedReader br = new BufferedReader(new InputStreamReader(System.in));                           String s = br.readLine();                          if (s != null && !s.trim().equals("")) {                              buffer.clear();                              buffer.put(s.getBytes());                              buffer.flip();                              sc.write(buffer);                              writed = true;                              if (s.equals("bye")) {                                  down = true;                                  break;                              }                          }                      }                      //if ((ops & SelectionKey.OP_READ) == SelectionKey.OP_READ && writed) {                      if (key.isReadable() && writed) {                          buffer.clear();                          sc.read(buffer);                          buffer.flip();                          byte[] b = new byte[buffer.limit()];                          buffer.get(b);                          print(new String(b));                          writed = false;                      }                  }                  selectionKeys.clear();              }          } catch(IOException e) {              e.printStackTrace();          }      }            private static void print(String s) {          System.out.println(s);      }  }

當然EchoClient也可以像下面這樣來實現(xiàn):

EchoClient2.java

package edu.dlut.zxf.nio;   import java.util.Set;  import java.io.BufferedReader;  import java.io.IOException;  import java.io.InputStreamReader;  import java.net.InetSocketAddress;  import java.net.InetAddress;  import java.nio.ByteBuffer;  import java.nio.channels.SelectionKey;  import java.nio.channels.Selector;  import java.nio.channels.SocketChannel;   /**   * Echo客戶端2   * @author finux   */ public class EchoClient2 {      public static void main(String[] args) {          ByteBuffer buffer = ByteBuffer.allocate(EchoServer.BUFFER_SIZE);          Selector selector = null;          SocketChannel sc = null;          try {              selector = Selector.open();              sc = SocketChannel.open();              sc.configureBlocking(false);              sc.register(selector, SelectionKey.OP_CONNECT);              sc.connect(new InetSocketAddress(InetAddress.getByName(EchoServer.HOST), EchoServer.PORT));              print("客戶端啟動,準備連接...");                            boolean writed = false;              boolean down = false;              while (!down && selector.select() > 0) {                                  Set<SelectionKey> selectionKeys = selector.selectedKeys();                  for (SelectionKey key: selectionKeys) {                                       //int ops = key.readyOps();                      //if ((ops & SelectionKey.OP_CONNECT) == SelectionKey.OP_CONNECT) {                      if (key.isConnectable()) {                          print("完成連接!");                          if (sc.isConnectionPending()) {                              sc.finishConnect();                          }                          sc.register(selector, SelectionKey.OP_READ | SelectionKey.OP_WRITE);                                      }                      //if ((ops & SelectionKey.OP_WRITE) == SelectionKey.OP_WRITE && !writed) {                      if (key.isWritable() && !writed) {                          //從準備IO中讀取內(nèi)容                          System.out.print("Input(bye to end): ");                          BufferedReader br = new BufferedReader(new InputStreamReader(System.in));                           String s = br.readLine();                          if (s != null && !s.trim().equals("")) {                              buffer.clear();                              buffer.put(s.getBytes());                              buffer.flip();                              sc.write(buffer);                              writed = true;                              if (s.equals("bye")) {                                  down = true;                                  break;                              }                          }                      }                      //if ((ops & SelectionKey.OP_READ) == SelectionKey.OP_READ && writed) {                      if (key.isReadable() && writed) {                          buffer.clear();                          sc.read(buffer);                          buffer.flip();                          byte[] b = new byte[buffer.limit()];                          buffer.get(b);                          print(new String(b));                          writed = false;                      }                  }                  selectionKeys.clear();              }          } catch(IOException e) {              e.printStackTrace();          }      }            private static void print(String s) {          System.out.println(s);      }  }

但是這樣的話,顯然EchoClient2中的while循環(huán)中的for循環(huán)(若有n次),在每次循環(huán)中都會多出n-1次if判斷,就是下面這個:

if (key.isConnectable()) {

到此,關(guān)于“怎么用nio實現(xiàn)Echo服務”的學習就結(jié)束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續(xù)學習更多相關(guān)知識,請繼續(xù)關(guān)注億速云網(wǎng)站,小編會繼續(xù)努力為大家?guī)砀鄬嵱玫奈恼拢?/p>

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

nio
AI