NIO 非阻塞网络编程快速入门

案例:

编写一个 NIO 入门案例,实现服务器端和客户端之间的数据简单通讯(非阻塞)

目的:理解 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;
import java.util.Set;public class NIOServer {public static void main(String[] args) throws Exception{//创建ServerSocketChannel -> ServerSocketServerSocketChannel serverSocketChannel = ServerSocketChannel.open();//得到一个Selecor对象Selector selector = Selector.open();//绑定一个端口6666, 在服务器端监听serverSocketChannel.socket().bind(new InetSocketAddress(6666));//设置为非阻塞serverSocketChannel.configureBlocking(false);//把 serverSocketChannel 注册到  selector 关心 事件为 OP_ACCEPT       pos_1serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);System.out.println("注册后的selectionkey 数量=" + selector.keys().size()); // 1//循环等待客户端连接while (true) {//这里我们等待1秒,如果没有事件发生, 返回if(selector.select(1000) == 0) { //没有事件发生System.out.println("服务器等待了1秒,无连接");continue;}//如果返回的>0, 就获取到相关的 selectionKey集合//1.如果返回的>0, 表示已经获取到关注的事件//2. selector.selectedKeys() 返回关注事件的集合//   通过 selectionKeys 反向获取通道Set<SelectionKey> selectionKeys = selector.selectedKeys();System.out.println("selectionKeys 数量 = " + selectionKeys.size());//遍历 Set<SelectionKey>, 使用迭代器遍历Iterator<SelectionKey> keyIterator = selectionKeys.iterator();while (keyIterator.hasNext()) {//获取到SelectionKeySelectionKey key = keyIterator.next();//根据key 对应的通道发生的事件做相应处理if(key.isAcceptable()) { //如果是 OP_ACCEPT, 有新的客户端连接//该该客户端生成一个 SocketChannelSocketChannel socketChannel = serverSocketChannel.accept(); //这里不会阻塞,会马上执行System.out.println("客户端连接成功 生成了一个 socketChannel " + socketChannel.hashCode());//将  SocketChannel 设置为非阻塞socketChannel.configureBlocking(false);//将socketChannel 注册到selector, 关注事件为 OP_READ, 同时给socketChannel//关联一个BuffersocketChannel.register(selector, SelectionKey.OP_READ, ByteBuffer.allocate(1024));System.out.println("客户端连接后 ,注册的selectionkey 数量=" + selector.keys().size()); //2,3,4..}if(key.isReadable()) {  //发生 OP_READ//通过key 反向获取到对应channelSocketChannel channel = (SocketChannel)key.channel();//获取到该channel关联的bufferByteBuffer buffer = (ByteBuffer)key.attachment();channel.read(buffer);System.out.println("from 客户端 " + new String(buffer.array()));}//手动从集合中移动当前的selectionKey, 防止重复操作keyIterator.remove();}}}
}

pos1:

1、对操作系统有一定了解的同学,就会大概知道这里监听的是一个Accept通道。这个通道的 作用就是监听,实际建立连接了还会有一个通道。
2、简单说一下为什么。因为客户端发请求的时候,服务器这边是肯定要先有一个监听通道,
监听某个端口是否有客户端要建立链接,如果有客户端想要建立链接,那么会再创建一个和 客户端真正通信的通道。
3、如果有其它客户端还想要建立链接,这个Accept监听端口监听到了,就会再创建几个真正 的通信通道。
4、也就是Server的一个端口可以建立多个TCP连接,因为IP层协议通过 目标地址+端口+源地址+源端口四个信息识别一个上下文

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, gujie~";//Wraps a byte array into a buffer,根绝字节数组的大小来调节buffer的大小ByteBuffer buffer = ByteBuffer.wrap(str.getBytes());//发送数据,将 buffer 数据写入 channelsocketChannel.write(buffer);System.in.read();}
}

运行结果

注意,为了可以让IDEA让客户端和服务端同时运行可以选择以下方式


注意:selector.selectedKeys()和selector.keys()不同,一个选择的所有注册过的客户端链接,一个是选择发生过事件的客户端链接。

SelectionKey

1.SelectionKey,表示 Selector 和网络通道的注册关系,共四种:
int OP_ACCEPT:有新的网络连接可以 accept,值为 16
int OP_CONNECT:代表连接已经建立,值为 8
int OP_READ:代表读操作,值为 1
int OP_WRITE:代表写操作,值为 4
————————————————
源码中:

public static final int OP_READ = 1 << 0;
public static final int OP_WRITE = 1 << 2;
public static final int OP_CONNECT = 1 << 3;
public static final int OP_ACCEPT = 1 << 4;

2.SelectionKey 相关方法

* public abstract Selector selector(),得到与之,关联的Selector对象
* public abstract SelectableChannel channel(),得到与之关联的通道
* public final Object attachment(),得到与之关联的共享数据
* public abstract SelectionKey interestOps(int ops),设置或改变监听事件
*  public final boolean isAcceptable(), 是否可以accept
* public final boolean isReadable(),是否可以读
* public final boolean isWritable(),是否可以写

ServerSocketChannel

1.ServerSocketChannel 在服务器端监听新的客户端 Socket 连接,负责监听,不负责实际的读写操作

2.相关方法如下

* public static ServerSocketChannel open(),得到- - 个ServerSocketChannel通道
* public final ServerSocketChannel bind(SocketAddress local),设置服务器端端口号
* public final SelectableChannel configureBlocking(boolean block),设置阻塞或非阻塞模式,取值false 表示采用非阻塞模式
* public SocketChannel accept(),接受-一个连接,返回代表这个连接的通道对象
* public final SelectionKey register(Selector sel, int ops),注册一个选择器并设置监听事件

SocketChannel

1.SocketChannel,网络 IO 通道,具体负责进行读写操作。NIO 把缓冲区的数据写入通道,或者把通道里的数据读到缓冲区。
2.相关方法如下

* public static ServerSocketChannel open(),得到一个ServerSocketChannel通道
* public final ServerSocketChannel bind(SocketAddress local),设置服务器端端口号
* public final SelectableChannel configureBlocking(boolean block),设置阻塞或非阻塞模式,取值false 表示采用非阻塞模式
* public SocketChannel accept(),接受-一个连接,返回代表这个连接的通道对象
* public final SelectionKey register(Selector sel, int ops),注册一个选择器并设置监听事件


ServerSocketChannel在服务端主要负责有一个连接来了,就生成一个socketChannel,而SocketChannel在客户端则主要负责数据的读写。

Java NIO 非阻塞网络编程快速入门相关推荐

  1. 高并发网络编程之NIO非阻塞网络编程

    文章目录 NIO非阻塞网络编程 Buffer缓冲区 Buffer工作原理: ByteBuffer内存类型 Channel通道 SocketChannel ServerSocketChannel Sel ...

  2. java nio非阻塞式网络通信入门案例 (nio服务端与bio多线程客户端(java/python)

    nio服务端: 改进服务端 java客户端 python版本客户端: python客户端改进版(多线程执行) 注意:如果想把服务端程序放在自己的服务器上,要记得开放相应的端口,否则客户端会显示连接超时 ...

  3. C++网络编程快速入门(四):EPOLL模型使用

    目录 基本使用方法 step1:创建epollfd step2:将fd绑定到epollfd step3:调用epoll_wait检测事件 epoll_wait与poll.select区别所在 水平触发 ...

  4. Java异步非阻塞编程的几种方式

    简介: Java异步非阻塞编程的几种方式 一. 从一个同步的Http调用说起 一个很简单的业务逻辑,其他后端服务提供了一个接口,我们需要通过接口调用,获取到响应的数据. 逆地理接口:通过经纬度获取这个 ...

  5. Fortran编程快速入门

    Fortran编程快速入门 1. 简介 1.1 FORTRAN语言发展概况 1.2 Fortran77和Fortran90的区别 1.3 Fortran和C/C++等大多数语言的不同 1.4 简单的 ...

  6. C++网络编程快速入门(二):Linux下使用select演示简单服务端程序

    目录 select参数解释 select使用规范 select使用缺点 基本流程 实例代码 通信效果演示 往期文章 select参数解释 extern int select (int __nfds, ...

  7. Java基础-SSM之mybatis快速入门篇

    Java基础-SSM之mybatis快速入门篇 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 其实你可能会问什么是SSM,简单的说就是spring mvc + Spring + m ...

  8. 转载博客:generic netlink 编程快速入门

    https://segmentfault.com/a/1190000016220770 generic netlink 编程快速入门

  9. pdf python 3.7编程快速入门 潘中强_无python基础,这些书籍可以帮您快速入门。

    利用Python进行数据分析> 定 价:119 元 作者:韦斯·麦金尼(Wes McKinney)著;徐敬一译 ISBN:9787111603702 出 版 社:机械工业出版社 学习Python ...

最新文章

  1. 信息系统项目管理知识--项目人力资源管理
  2. .NET代码编写规范 整理
  3. 广东48.6万人资产超600万 华东超600万人群最多
  4. Python文本处理2个小案例(文本嗅探与关键词占比统计)
  5. php3源码分析,ThinkPHP3.1.3源码分析(一) 入口文件分析
  6. Typora如何设置图片的默认保存路径
  7. 采购物联网卡如何选择流量套餐
  8. 深入浅出23种设计模式(最全面)
  9. 基于Matlab的车牌号识别
  10. iconfont阿里矢量图标库的引入与使用
  11. 装机电脑用什么软件测试,有什么一键装机的软件比较好用?
  12. html表格的基础知识及源代码-尚硅谷
  13. 在Chrome浏览器添加IDM插件——顽强版
  14. 计算机专业课件ppt背景,ppt背景图片怎么设置
  15. 百度wz开户竞价推广如何做到降低平均点击价格
  16. 软考 - 高级信息系统项目管理师,考证好处、报考流程及知识体系
  17. ASM(五) 利用TreeApi 解析生成及转换Class
  18. QQ、旺旺、MSN、SKYPE在线代码生成!
  19. HTTP Status 404 / tomcat 404问题解决
  20. 复杂截面的形心和惯性矩如何计算(萌新求教)

热门文章

  1. 腾讯获准在中国销售Switch游戏机 任天堂股价应声飙升逾14%
  2. l298n电机哪一端为正_汽车维修要知道的几个答案,交流发电机、调节器有什么功用?...
  3. 智慧讲台必须支持的协议
  4. hashmap扩容线程安全问题_HashMap在1.7 1.8中的线程安全问题
  5. tracker服务器列表2020_个人服务器采购整理分享
  6. H3C三层交换机划分VLAN示例
  7. java比较吊的程序代码_java中 compareTo()的程序代码及用法
  8. 【Flink】Flink 1.13 Flink SQL 新特性 性能优化 时区 时间 纠正
  9. 【ElasticSearch】Es 源码之 PersistentTasksExecutorRegistry 源码解读
  10. 40-400-044-运维-优化-MySQL order by 优化