文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

怎么用nio实现Echo服务

2023-06-17 11:49

关注

这篇文章主要介绍“怎么用nio实现Echo服务”,在日常操作中,相信很多人在怎么用nio实现Echo服务问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”怎么用nio实现Echo服务”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

今天突然间想用nio实现个Echo服务,程序实现起来实现不算困难,但跑起来后,在Server端的ServerSocket完成accept之后,我的CPU总是跳到100%。嗯,小郁闷,后来,才发现自己在Server端注册了多余的监听事件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;    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;          //缓冲区          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("读取的内容为:" + 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;    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也可以像下面这样来实现:

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;    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中读取内容                          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循环中的for循环(若有n次),在每次循环中都会多出n-1次if判断,就是下面这个:

if (key.isConnectable()) {

到此,关于“怎么用nio实现Echo服务”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注编程网网站,小编会继续努力为大家带来更多实用的文章!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯