9.NIO非阻塞式网络通信入门

这篇具有很好参考价值的文章主要介绍了9.NIO非阻塞式网络通信入门。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


highlight: arduino-light

Selector 示意图和特点说明

一个 I/O 线程可以并发处理 N 个客户端连接和读写操作,这从根本上解决了传统同步阻塞 I/O 一连接一线程模型。架构的性能、弹性伸缩能力和可靠性都得到了极大的提升。

9.NIO非阻塞式网络通信入门,nio,python,开发语言

服务端流程

  • 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);

    1. 轮询式的获取选择器上已经“准备就绪”的事件
  • java //轮询式的获取选择器上已经“准备就绪”的事件,大于0 说明存在 准备就绪的事件 while (selector.select() > 0) {        System.out.println("轮一轮");        //7. 获取当前选择器中所有注册的“选择键(已就绪的监听事件)”        Iterator<SelectionKey> 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. 获取当前选择器中所有注册的“选择键(已就绪的监听事件)”            Iterator<SelectionKey> 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 serverSocketChannel=ServerSocketChannel.open(); //2. 得到一个Selector对象 Selector selector=Selector.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 keyIterator=selector.selectedKeys().iterator(); while(keyIterator.hasNext()){ SelectionKey key=keyIterator.next(); if(key.isAcceptable()){ //客户端连接请求事件 SocketChannel socketChannel=serverSocketChannel.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文章来源地址https://www.toymoban.com/news/detail-611133.html

到了这里,关于9.NIO非阻塞式网络通信入门的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 阻塞非阻塞IO(BIO和NIO),IO多路复用

    1.概念 NIO(New Input/Output)和BIO(Blocking Input/Output)是Java中用于处理输入输出的两种不同的模型。   BIO 会 阻塞 ,等有了消息,立刻返回,一个线程处理一个recv(需要很多线程)。 NIO 有没有消息,都返回(但程序要自己判断,返回空就循环重复);一个线程可以处理多个

    2024年02月09日
    浏览(40)
  • 【JAVA基础】- 同步非阻塞模式NIO详解

    NIO(Non-Blocking IO)是同步非阻塞方式来处理IO数据。服务器实现模式为一个请求一个线程,即客户端发送的链接请求都会注册到选择器上,选择器轮询到连接有IO请求时才启动一个线程进行处理。 同步(synchronous) :调用方式指应用(Application),调用方发起有一个功能调用时,在

    2024年02月13日
    浏览(42)
  • 快速入门java网络编程基础------Nio

    哔哩哔哩黑马程序员 netty实战视频 NIO(New I/O)是Java中提供的一种基于通道和缓冲区的I/O(Input/Output)模型。它是相对于传统的IO(InputStream和OutputStream)模型而言的新型I/O模型。NIO的主要特点包括: 1.通道与缓冲区: 2.NIO引入了通道(Channel)和缓冲区(Buffer)的概念。通道

    2024年01月20日
    浏览(52)
  • 为什么Tomcat的NIO在读取body时要模拟阻塞?

    文章首发地址 Tomcat的NIO完全可以以非阻塞方式处理IO,为什么在读取body部分时要模拟阻塞呢?在Tomcat的NIO读取HTTP请求时,为了保证请求的正确性和可靠性,需要模拟阻塞模式,这是因为servlet规范里定义了ServletInputStream在读数据时是阻塞模式。 ServletInputStream在读取数据时是阻

    2024年02月13日
    浏览(51)
  • Java NIO(Java Non-Blocking IO:非阻塞式IO)(2)

    1.NIO非阻塞网络编程相关的(Selector、SelectionKey、ServerScoketChannel和SocketChannel)关系梳理图: 说明: ①.当客户端连接时,会通过服务器端ServerSocketChannel得到/生成对应的SocketChannel; ②.通过register(Selector sel,int ops)方法将SocketChannel注册到Selector上(一个Selector上可以注册多个SocketChannel); ③

    2024年02月02日
    浏览(46)
  • NIO通信代码示例

    NioClient NioClientHandle NioServer NioServerHandle 先启动server再启动client

    2024年01月24日
    浏览(35)
  • 计算机网络:网络通信相关概念入门

    网络发展背景:   最初的计算机是单机,那么单机是这样传输数据的:A单机和B单机,在A单机处理完数据后,将装有数据的存储介质交付给B单机,然后B单机读取数据并处理。毫无疑问,这样太麻烦了。   因此逐步诞生了网络的概念,使用网络来进行数据的传输,大大提

    2024年02月13日
    浏览(47)
  • 聊聊分布式架构06——[NIO入门]简单的Netty NIO示例

    目录 Java NIO和Netty NIO比较 Java NIO: Netty: Netty NIO中的主要模块 Transport(传输层) Buffer(缓冲区) Codec(编解码器) Handler(处理器) EventLoop(事件循环) Bootstrap和Channel(引导和通道) Future和Promise(异步编程) Netty示例 服务端时序图 服务端代码 客户端时序图 客户端代码

    2024年02月07日
    浏览(36)
  • Android网络开发(一、Socket通信&HTTP通信)

      Socket:即套接字,其本身并不是一种通信协议,它是封装了TCP/IP、UDP 协议的API实现。在创建Socket对象后,底层会完成TCP/IP的三次握手等(UDP协议对应的API是DatagramSocket)。   在建立了Socket连接后,就可以和服务端进行Socket通信了。常用的Socket通信包含发送数据、接收数

    2024年02月12日
    浏览(69)
  • AUTOSAR从入门到精通-网络通信(UDPNm)(一)

    目录  前言 几个相关概念 原理 什么是UdpNm 约束和假设  限制

    2024年02月03日
    浏览(45)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包