数据通信流程:

通过selector.select()阻塞方法获取到感兴趣事件的key,根据key定位到channel,通过channel的读写操作进行数据通信。channel的read或者write操作都是通过buffer进行的。

代码示例

Server:

public class Server {
public static void main(String[] args) throws InterruptedException {
final int port = 9999;
try {
// 初始化server
ServerSocketChannel server = ServerSocketChannel.open();
server.socket().bind(new InetSocketAddress(port));
Selector selector = Selector.open(); // 这一步的设置在register中需要用到,所以要在register之前设置,否则会发生异常
server.configureBlocking(false);
SelectionKey serverKey = server.register(selector, SelectionKey.OP_ACCEPT); ByteBuffer buffer = ByteBuffer.allocate(50);
// 事件循环
while(true) {
Thread.sleep(500);
selector.select();
Set<SelectionKey> keys = selector.selectedKeys();
Iterator<SelectionKey> iterator = keys.iterator();
while (iterator.hasNext()) {
SelectionKey key = iterator.next();
iterator.remove();
if (!key.isValid()) {
continue;
}
if (key.isAcceptable()) {
ServerSocketChannel ssc = (ServerSocketChannel) key.channel();
SocketChannel sc = ssc.accept();
sc.configureBlocking(false);
sc.register(selector, SelectionKey.OP_READ | SelectionKey.OP_WRITE);
// System.out.println(serverKey == key);
continue;
}
if (key.isReadable()) {
SocketChannel sc = (SocketChannel) key.channel();
sc.read(buffer);
buffer.flip();
System.out.println(new String(buffer.array(), 0, buffer.limit()));
}
if (key.isWritable()) {
SocketChannel sc = (SocketChannel) key.channel();
sc.write(ByteBuffer.wrap("I am server!".getBytes()));
}
}
} } catch (IOException e) {
e.printStackTrace();
}
}
}

Client:

public class Client {
public static void main(String[] args) throws IOException, InterruptedException {
SocketChannel client = SocketChannel.open();
client.connect(new InetSocketAddress("localhost", 9999));
client.configureBlocking(false); ByteBuffer buffer = ByteBuffer.allocate(50);
while (true) {
buffer.clear();
int i = client.read(buffer);
if (i > 0) {
buffer.flip();
System.out.println(new String(buffer.array(), 0, buffer.limit()));
} client.write(ByteBuffer.wrap("I am a client!".getBytes()));
Thread.sleep(500);
}
}
}

其他

运行在Linux kernel 2.6以后的OS中的Java应用,NIO的底层实现是根据OS提供的io多路复用接口epoll实现。

参考资料

Java NIO工作原理的更多相关文章

  1. 全面解读Java NIO工作原理(4)

    全面解读Java NIO工作原理(4) 2011-12-14 10:31 Rollen Holt Rollen Holt的博客 我要评论(0) 字号:T | T JDK 1.4 中引入的新输入输出 ( ...

  2. 全面解读Java NIO工作原理(3)

    全面解读Java NIO工作原理(3) 2011-12-14 10:31 Rollen Holt Rollen Holt的博客 我要评论(0) 字号:T | T JDK 1.4 中引入的新输入输出 ( ...

  3. 全面解读Java NIO工作原理(2)

    全面解读Java NIO工作原理(2) 2011-12-14 10:31 Rollen Holt Rollen Holt的博客 我要评论(0) 字号:T | T JDK 1.4 中引入的新输入输出 ( ...

  4. 全面解读Java NIO工作原理(1)

    全面解读Java NIO工作原理(1) 2011-12-14 10:31 Rollen Holt Rollen Holt的博客 我要评论(0) 字号:T | T JDK 1.4 中引入的新输入输出 ( ...

  5. JAVA NIO工作原理及代码示例

    简介:本文主要介绍了JAVA NIO中的Buffer, Channel, Selector的工作原理以及使用它们的若干注意事项,最后是利用它们实现服务器和客户端通信的代码实例. 欢迎探讨,如有错误敬请 ...

  6. (前篇:NIO系列 推荐阅读) Java NIO 底层原理

    出处: Java NIO 底层原理 目录 1.1. Java IO读写原理 1.1.1. 内核缓冲与进程缓冲区 1.1.2. java IO读写的底层流程 1.2. 四种主要的IO模型 1.3. 同步 ...

  7. Java虚拟机工作原理详解 (一)

    一.类加载器 首先来看一下java程序的执行过程. 从这个框图很容易大体上了解java程序工作原理.首先,你写好java代码,保存到硬盘当中.然后你在命令行中输入 javac YourClassNam ...

  8. Java虚拟机工作原理详解

    原文地址:http://blog.csdn.net/bingduanlbd/article/details/8363734 一.类加载器 首先来看一下java程序的执行过程. 从这个框图很容易大体上了 ...

  9. Java虚拟机工作原理具体解释

    一.类载入器 首先来看一下java程序的运行过程. 从这个框图非常easy大体上了解java程序工作原理.首先,你写好java代码,保存到硬盘其中.然后你在命令行中输入 javac YourClass ...

随机推荐

  1. One EEG preprocessing pipeline - EEG-fMRI paradigm

    The preprocessing pipeline of EEG data from EEG-fMRI paradigm differs from that of regular EEG data, ...

  2. mysql: Illegal mix of collations (utf8_unicode_ci,IMPLICIT) and (utf8_general_ci,IMPLICIT) for operation '= 的解决

    昨天把mysql里所有table的varchar字段的字符集,批量换成了utf8mb4/utf8mb4_unicode_ci ,以便能保存一些emoji火星文 , 结果有一个sql语句执行时,报错如下 ...

  3. css设置select高度(IE,FF,Chrome)[转]

    大家都知道select是无法设置高度和边框颜色等等的在ie67下面,其他的都是可以的,所以有时候为了在所有的浏览器下显示都一致,就使用了 js的模拟,这个是大家经常碰到的,js不光要模拟外观还有模拟事 ...

  4. jq实现点击某元素之外触发事件

    <script type="text/javascript"> $(document).bind("click",function(e){ var ...

  5. MyBatis的Mapper文件的foreach标签详解

    MyBatis的Mapper文件的foreach标签用来迭代用户传递过来的Lise或者Array,让后根据迭代来拼凑或者批量处理数据.如:使用foreach来拼接in子语句. 在学习MyBatis M ...

  6. 自己积累的一些Emgu CV代码(主要有图片格式转换,图片裁剪,图片翻转,图片旋转和图片平移等功能)

    using System; using System.Drawing; using Emgu.CV; using Emgu.CV.CvEnum; using Emgu.CV.Structure; na ...

  7. python3中用HTMLTestRunner.py报ImportError: No module named 'StringIO'如何解决

    python3中用HTMLTestRunner.py报ImportError: No module named 'StringIO'的解决方法: 1.原因是官网的是python2语法写的,看官手动把官 ...

  8. MySQL的insert语句的区别

    SQL Server: insert into tb_articleType (articleType_name,articleType_info) values ("test", ...

  9. Git初级实践教程(图文)

    关于Git Git的由来 Linux 的创始人 Linus Torvalds 在 2005 年开发了 Git 的原型程序.当时,由于在 Linux 内核开发中使用的既有版本管理系统的开发方许可证发生了 ...

  10. Sql简单封装

    public class SqlHelper { public static string SqlConnectionStr = ConfigurationManager.ConnectionStri ...