数据库网站建设公司,大连网络建站模板,网站开始怎么做的,厦门网站开发费用highlight: arduino-light Selector 示意图和特点说明 一个 I/O 线程可以并发处理 N 个客户端连接和读写操作#xff0c;这从根本上解决了传统同步阻塞 I/O 一连接一线程模型。架构的性能、弹性伸缩能力和可靠性都得到了极大的提升。 服务端流程 1、当客户端连接服务端时… highlight: arduino-light Selector 示意图和特点说明 一个 I/O 线程可以并发处理 N 个客户端连接和读写操作这从根本上解决了传统同步阻塞 I/O 一连接一线程模型。架构的性能、弹性伸缩能力和可靠性都得到了极大的提升。 服务端流程 1、当客户端连接服务端时服务端会通过 ServerSocketChannel 得到 SocketChannel:获取通道 java ServerSocketChannel ssChannel ServerSocketChannel.open(); 2、切换非阻塞模式 java ssChannel.configureBlocking(false); 3、绑定连接 java ssChannel.bind(new InetSocketAddress(9999)); 4、 获取选择器 java Selector selector Selector.open(); 5、 将通道注册到选择器上, 并且指定“监听接收事件” java ssChannel.register(selector, SelectionKey.OP_ACCEPT); 轮询式的获取选择器上已经“准备就绪”的事件java //轮询式的获取选择器上已经“准备就绪”的事件,大于0 说明存在 准备就绪的事件 while (selector.select() 0) { System.out.println(轮一轮); //7. 获取当前选择器中所有注册的“选择键(已就绪的监听事件)” IteratorSelectionKey it selector.selectedKeys().iterator(); while (it.hasNext()) { //8. 获取准备“就绪”的是事件 SelectionKey sk it.next(); //9. 判断具体是什么事件准备就绪 if (sk.isAcceptable()) { //10. 若“接收就绪”获取客户端连接 SocketChannel sChannel ssChannel.accept(); //11. 切换非阻塞模式 sChannel.configureBlocking(false); //12. 将该通道注册到选择器上并修改注册事件为read sChannel.register(selector, SelectionKey.OP_READ); } else if (sk.isReadable()) { //13. 获取当前选择器上“读就绪”状态的通道 SocketChannel sChannel (SocketChannel) sk.channel(); //14. 读取数据 ByteBuffer buf ByteBuffer.allocate(1024); int len 0; while ((len sChannel.read(buf)) 0) { buf.flip(); System.out.println(new String(buf.array(), 0, len)); buf.clear(); } } //15. 处理完毕 移除选择键 SelectionKey it.remove(); } } } 客户端流程 1.获取通道 java SocketChannel sChannel SocketChannel.open(new InetSocketAddress(127.0.0.1, 9999)); 2.切换非阻塞模式 java sChannel.configureBlocking(false); 3.分配指定大小的缓冲区 java ByteBuffer buf ByteBuffer.allocate(1024); 4.发送数据给服务端 java Scanner scan new Scanner(System.in); while(scan.hasNext()){ String message scan.nextLine(); buf.put((new SimpleDateFormat(yyyy/MM/dd HH:mm:ss).format(System.currentTimeMillis()) \n message).getBytes()); buf.flip(); sChannel.write(buf); buf.clear(); } //关闭通道 sChannel.close(); NIO非阻塞式网络通信入门案例 需求服务端接收客户端的连接请求并接收多个客户端发送过来的事件。 代码案例 java /** 客户端 */ public class Client { public static void main(String[] args) throws Exception { //1. 获取通道 - SelectionKey.OP_ACCEPT 对应监听接收事件 SocketChannel sChannel SocketChannel.open(new InetSocketAddress(127.0.0.1, 9999)); //2. 切换非阻塞模式 sChannel.configureBlocking(false); //3. 分配指定大小的缓冲区 ByteBuffer buf ByteBuffer.allocate(1024); //4. 发送数据给服务端 Scanner scan new Scanner(System.in); while(scan.hasNext()){ String message scan.nextLine(); buf.put((new SimpleDateFormat(yyyy/MM/dd HH:mm:ss).format(System.currentTimeMillis()) \n message).getBytes()); buf.flip(); //客户端写对应服务器端读就绪 sChannel.write(buf); buf.clear(); } //5. 关闭通道 sChannel.close(); } } /** 服务端 */ public class Server { public static void main(String[] args) throws IOException { //1. 获取通道 ServerSocketChannel ssChannel ServerSocketChannel.open(); //2. 切换非阻塞模式 ssChannel.configureBlocking(false); //3. 绑定连接 ssChannel.bind(new InetSocketAddress(9999)); //4. 获取选择器 Selector selector Selector.open(); //5. 将通道注册到选择器上, 并且指定“监听接收事件” ssChannel.register(selector, SelectionKey.OP_ACCEPT); //6. 轮询式的获取选择器上已经“准备就绪”的事件 while (selector.select() 0) { System.out.println(轮一轮); //7. 获取当前选择器中所有注册的“选择键(已就绪的监听事件)” IteratorSelectionKey it selector.selectedKeys().iterator(); while (it.hasNext()) { //8. 获取准备“就绪”的是事件 SelectionKey sk it.next(); //9. 判断具体是什么事件准备就绪 if (sk.isAcceptable()) { //10. 若“接收就绪”获取客户端连接 SocketChannel sChannel ssChannel.accept(); //11. 切换非阻塞模式 sChannel.configureBlocking(false); //12. 将该通道注册到选择器上 这里可以把缓存指定上 sChannel.register(selector, SelectionKey.OP_READ); } else if (sk.isReadable()) { //13. 获取当前选择器上“读就绪”状态的通道 SocketChannel sChannel (SocketChannel) sk.channel(); //14. 读取数据 ByteBuffer buf ByteBuffer.allocate(1024); int len 0; while ((len sChannel.read(buf)) 0) { buf.flip(); System.out.println(new String(buf.array(), 0, len)); buf.clear(); } } //15. 取消选择键 SelectionKey it.remove(); } } } } 尚硅谷代码案例 java package com.atguigu.nio; 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.Iterator; //网络服务器端程序 public class NIOServer { public static void main(String[] args) throws Exception{ //1. 得到一个ServerSocketChannel对象 ServerSocketChannel serverSocketChannelServerSocketChannel.open(); //2. 得到一个Selector对象 Selector selectorSelector.open(); //3. 绑定一个端口号, 在服务器的6666监听 2个方式有什么区别 //serverSocketChannel.bind(new InetSocketAddress(6666)); serverSocketChannel.socket().bind(new InetSocketAddress(6666)); //4. 设置非阻塞方式 serverSocketChannel.configureBlocking(false); //5. 把ServerSocketChannel对象注册给Selector对象 serverSocketChannel.register(selector, SelectionKey.OPACCEPT); //6. 干活 while(true){ //6.1 监控客户端 //如果使用 selector.select() 就会阻塞在这里的 if(selector.select(1000)0){ //nio非阻塞式的优势 System.out.println(Server:等待了1秒无客户端连接); continue; } //6.2 得到SelectionKey,判断通道里的事件 Iterator keyIteratorselector.selectedKeys().iterator(); while(keyIterator.hasNext()){ SelectionKey keykeyIterator.next(); if(key.isAcceptable()){ //客户端连接请求事件 SocketChannel socketChannelserverSocketChannel.accept(); socketChannel.configureBlocking(false); socketChannel.register(selector,SelectionKey.OP READ, ByteBuffer.allocate(1024)); } if(key.isReadable()){ //读取客户端数据事件 SocketChannel channel(SocketChannel) key.channel(); ByteBuffer buffer(ByteBuffer) key.attachment(); channel.read(buffer); System.out.println(接收到客户端数据new String(buffer.array())); } // 6.3 手动从集合中移除当前key,防止重复处理 keyIterator.remove(); } } } } java package com.atguigu.nio; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.SocketChannel; public class NIOClient { public static void main(String[] args) throws Exception{ //得到一个网络通道 SocketChannel socketChannel SocketChannel.open(); //设置非阻塞 socketChannel.configureBlocking(false); //提供服务器端的ip 和 端口 InetSocketAddress inetSocketAddress new InetSocketAddress(127.0.0.1, 6666); //连接服务器 if (!socketChannel.connect(inetSocketAddress)) { while (!socketChannel.finishConnect()) { System.out.println(因为连接需要时间客户端不会阻塞可以做其它工作..); } } //...如果连接成功就发送数据 String str hello, 尚硅谷~; //Wraps a byte array into a buffer ByteBuffer buffer ByteBuffer.wrap(str.getBytes()); // 发送数据将 buffer 数据写入 channel socketChannel.write(buffer); System.in.read(); } } 使用6666端口有个坑爹的地方,端口号被占用。 解决:https://www.cnblogs.com/jf-67/p/8425405.html 原因:https://blog.csdn.net/hi_pig2003/article/details/52995528