Java NIO案例
Java 网络IO编程总结(BIO、NIO、AIO均含完整实例代码) http://blog.csdn.net/anxpp/article/details/51512200
Java NIO框架Netty简单使用 http://blog.csdn.net/anxpp/article/details/52139155
使用最新Netty实现一个简单的聊天程序 http://blog.csdn.net/anxpp/article/details/52139155
服务端、客户端
package com.dsp.nio; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import java.io.IOException;
import java.net.InetSocketAddress;
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; /**
*
* 监控是否可连接、可读、可写
*
* 代码中巧妙使用了SocketChannel的attach功能,将Hanlder和可能会发生事件的channel链接在一起,当发生事件时,可以立即触发相应链接的Handler
*
*/
public class Reactor implements Runnable { private static Logger log = LoggerFactory.getLogger(Reactor.class); final Selector selector; final ServerSocketChannel serverSocket; /**
* 服务端配置初始化,监听端口
* @param port
* @throws IOException
*/
public Reactor(int port) throws IOException {
this.selector = Selector.open();
this.serverSocket = ServerSocketChannel.open();
this.serverSocket.socket().bind(new InetSocketAddress(port));
this.serverSocket.configureBlocking(false);
SelectionKey selectionKey = this.serverSocket.register(selector, SelectionKey.OP_ACCEPT);
// 利用selectionKey的attache功能绑定Acceptor 如果有事情,触发Acceptor
selectionKey.attach(new Acceptor());
log.info("===>>> attach(new Acceptor())");
}
/*
* SPI
*/
// Alternatively, use explicit SPI provider
// SelectorProvider selectorProvider = SelectorProvider.provider();
// selector = selectorProvider.openSelector();
// serverSocket = selectorProvider.openServerSocketChannel(); /**
* 分发请求
*
* @param selectionKey
*/
void dispatch(SelectionKey selectionKey) {
Runnable run = (Runnable) (selectionKey.attachment());
if (run != null) {
run.run();
}
} /**
* 监听连接和channel是否就绪
*/
public void run() {
try {
/**
* 线程未被中断
*/
while (!Thread.interrupted()) {
int readySize = this.selector.select();
log.info("I/O ready size = {}", readySize);
Set<?> selectedKeys = this.selector.selectedKeys();
Iterator<?> iterator = selectedKeys.iterator();
// Selector如果发现channel有OP_ACCEPT或READ事件发生,下列遍历就会进行。
while (iterator.hasNext()) {
/*
* 一个新的连接,第一次出发Accepter线程任务,之后触发Handler线程任务
*/
SelectionKey selectionKey = (SelectionKey) iterator.next();
log.info("===>>> acceptable = {}, connectable = {}, readable = {}, writable = {}.",
selectionKey.isAcceptable(), selectionKey.isConnectable(),
selectionKey.isReadable(), selectionKey.isWritable());
dispatch(selectionKey);
}
selectedKeys.clear();
}
} catch (IOException ex) {
log.info("reactor stop!" + ex);
}
} /**
* 处理新连接
*
* @author dsp
*
*/
class Acceptor implements Runnable { @Override
public void run() {
try {
log.debug("===>>> ready for accept!");
SocketChannel socketChannel = serverSocket.accept();
if (socketChannel != null) {
new Handler(selector, socketChannel);
}
} catch (IOException ex) {
/* . . . */
}
} } }
package com.dsp.nio; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel; /**
*
* 处理读写
*
*/
final class Handler implements Runnable { private static Logger log = LoggerFactory.getLogger(Reactor.class); static final int MAX_IN = 1024; static final int MAX_OUT = 1024; ByteBuffer inputBuffer = ByteBuffer.allocate(MAX_IN); ByteBuffer output = ByteBuffer.allocate(MAX_OUT); final SocketChannel socketChannel; final SelectionKey selectionKey; static final int READING = 0, SENDING = 1; int state = READING; /**
* 注意在Handler里面又执行了一次attach,覆盖前面的Acceptor,下次该Handler又有READ事件发生时,将直接触发Handler,从而开始了数据的
* “读 -> 处理 -> 写 -> 发出” 等流程处理。
*
* @param selector
* @param socketChannel
* @throws IOException
*/
Handler(Selector selector, SocketChannel socketChannel) throws IOException {
this.socketChannel = socketChannel;
this.socketChannel.configureBlocking(false);
this.selectionKey = this.socketChannel.register(selector, 0);
this.selectionKey.attach(this);
this.selectionKey.interestOps(SelectionKey.OP_READ);
// selector.wakeup();
} /**
* 只是返回true,具体的判断没有实现
*
* @return
*/
boolean inputIsComplete() {
return true;
} /**
* 只是返回true,具体的判断没有实现
*
* @return
*/
boolean outputIsComplete() {
return true;
} /**
* 处理数据(无具体实现)
*/
void process(String msg) {
// output.put("hello world, hello dsp!".getBytes());
String outMsg = "out + " + msg;
output.put(outMsg.getBytes());
output.flip();
} /**
* 读取请求数据并处理
*
* @throws IOException
*/
void read() throws IOException {
log.info("===>>> read into bytebuffer from socketchannel inputs.");
if (inputIsComplete()) {
socketChannel.read(inputBuffer);
inputBuffer.flip();
byte[] inputBytes = new byte[inputBuffer.limit()];
inputBuffer.get(inputBytes);
String inputString = new String(inputBytes);
log.info("===>>> 从客户端读取请求信息 = {}", inputString);
log.info("===>>> read complete."); process(inputString); state = SENDING;
// 读完了数据之后,注册OP_WRITE事件
selectionKey.interestOps(SelectionKey.OP_WRITE);
}
} /**
* 返回响应信息
*
* @throws IOException
*/
void send() throws IOException {
log.info("===>>> write into socketchannel from bytebuffer outputs");
socketChannel.write(output);
if (outputIsComplete()) {
// The key will be removed from all of the selector's key sets during the next
// selection operation.
selectionKey.cancel();
// 关闭通过,也就关闭了连接
socketChannel.close();
log.info("===>>> close socketchannel after write complete");
}
} @Override
public void run() {
try {
if (state == READING)
read();
else if (state == SENDING)
send();
} catch (IOException ex) {
/* . . . */
}
} }
package com.dsp.nio; import java.io.IOException; /**
*
* Model: Reactor in SingleThread
*
* 利用NIO多路复用机制,多路IO复用一个线程
*
* @author dsp
*
*/
public class ReactorInSingleThreadServer { public static void main(String args[]) throws IOException {
Reactor reactor = new Reactor(9999);
reactor.run(); // 不会开启线程,相当于普通方法调用
} }
package com.dsp.nio; import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
import java.util.concurrent.LinkedBlockingQueue; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; /**
*
* 访问NIO服务器的客户端
*
* @author dsp
*
*/
public class ReactorInSingleThreadClient extends Thread { private static Logger log = LoggerFactory.getLogger(ReactorInSingleThreadClient.class); private static LinkedBlockingQueue<Thread> failureQueue = new LinkedBlockingQueue<Thread>(); @Override
public void run() {
try {
ByteBuffer buffer = ByteBuffer.allocate(1024);
SocketChannel socketChannel = SocketChannel.open();
boolean connected = socketChannel.connect(new InetSocketAddress(9999));
if (connected) {
log.info("===>>> 和服务器 {} 已连接...", socketChannel.getRemoteAddress());
/*
* 请求
*/
String msg = "in + 你好,dsp!" + Thread.currentThread().getName();
buffer.put(msg.getBytes());
buffer.flip();
socketChannel.write(buffer);
buffer.clear(); /*
* 响应
*/
buffer.clear();
socketChannel.read(buffer);
buffer.flip();
byte[] data = new byte[buffer.limit()];
buffer.get(data);
String string = new String(data);
log.info("===>>> " + string);
buffer.clear(); socketChannel.close();
} else {
log.error("连不上服务器...");
}
} catch (java.net.ConnectException e) {
failureQueue.offer(this);
} catch (Exception e) {
e.printStackTrace();
}
} public static void main(String[] args) throws IOException, InterruptedException {
int maxThreads = 3000;
while (maxThreads-- > 0) {
new Thread(new ReactorInSingleThreadClient()).start();
} Thread.sleep(Integer.MAX_VALUE);
} }
^_^
Java NIO案例的更多相关文章
- Java NIO (转)
Java NIO提供了与标准IO不同的IO工作方式: Channels and Buffers(通道和缓冲区):标准的IO基于字节流和字符流进行操作的,而NIO是基于通道(Channel)和缓冲区(B ...
- 【转】java NIO 相关知识
原文地址:http://www.iteye.com/magazines/132-Java-NIO Java NIO(New IO)是从Java 1.4版本开始引入的一个新的IO API,可以替代标准的 ...
- java nio 与io区别
转自:http://blog.csdn.net/keda8997110/article/details/19549493 当学习了Java NIO和IO的API后,一个问题马上涌入脑海: 我应该何时使 ...
- 攻破JAVA NIO技术壁垒
转载自攻破JAVA NIO技术壁垒 概述 NIO主要有三大核心部分:Channel(通道),Buffer(缓冲区), Selector.传统IO基于字节流和字符流进行操作,而NIO基于Channel和 ...
- Java IO和Java NIO在文件拷贝上的性能差异分析
1. 在JAVA传统的IO系统中,读取磁盘文件数据的过程如下: 以FileInputStream类为例,该类有一个read(byte b[])方法,byte b[]是我们要存储读取到用户空间的缓冲区 ...
- Java NIO中核心组成和IO区别
1.Java NIO核心组件 Java NIO中有很多类和组件,包括Channel,Buffer 和 Selector 构成了核心的API.其它组件如Pipe和FileLock是与三个核心组件共同使用 ...
- Java NIO 和 IO 的区别详解
Java NIO为jdk1.4提供了新的API,本文主要来比较一下Java中NIO和IO的区别,Java初学者可以了解一下. 下表总结了Java NIO和IO之间的主要差别,我会更详细地描述表中每部分 ...
- Java NIO 转载
原文:http://www.iteye.com/magazines/132-Java-NIO Java NIO 系列教程 2014-04-28 编辑 wangguo 评论(71条) 有204256 ...
- Java NIO与IO
当学习了Java NIO和IO的API后,一个问题立即涌入脑海: 我应该何时使用IO,何时使用NIO呢?在本文中,我会尽量清晰地解析Java NIO和IO的差异.它们的使用场景,以及它们怎样影响您的代 ...
随机推荐
- 每日英语:Philippine Chapel Becomes a Medical Center
In the darkest moments of the killer storm that ripped across this coastal city on Friday, residents ...
- [开源项目-MyBean轻量级配置框架] MyBean的特性和MyBean的开始
[概述] 自从mBean框架出生后,受到很多朋友的关注,在公司的外包项目中得到了不错的应用.由于mBean是公司的项目,不便开源,于是这几天利用晚上的时间和周末的时间重写了底层beanMananger ...
- java 多线程 22 :生产者/消费者模式 进阶 利用await()/signal()实现
java多线程15 :wait()和notify() 的生产者/消费者模式 在这一章已经实现了 wait/notify 生产消费模型 利用await()/signal()实现生产者和消费者模型 一样 ...
- 利用jenkins的api来完成相关工作流程的自动化
[本文出自天外归云的博客园] 背景 1. 实际工作中涉及到安卓客户端方面的测试,外推或运营部门经常会有很多的渠道,而每个渠道都对应着一个app的下载包,这些渠道都记录在安卓项目下的一个渠道列表文件中. ...
- JAVA-JSP内置对象之移除属性
相关资料:<21天学通Java Web开发> 移除属性1.只需调用相应对象的removeAttribute()方法就可以移除指定属性 RemoveAttributeDemo.jsp < ...
- in linux system of ftp command
一口流利的english title 常用命令: ftp baidu.com ftp>ls ftp>cd directory ftp>get filename 下载 ftp>p ...
- How Not to Crash #2: Mutation Exceptions 可变异常(不要枚举可变的集合)
How Not to Crash #2: Mutation Exceptions 可变异常html, body {overflow-x: initial !important;}html { font ...
- 微软开放了.NET 4.5.1的源代码
您目前处于: InfoQ首页 新闻 微软开放了.NET 4.5.1的源代码 微软开放了.NET 4.5.1的源代码 作者 姚琪琳 发布于 二月 26, 2014 | 1 讨论 新浪微博腾讯微博豆瓣 ...
- CentOS服务器简单判断CC攻击的命令
使用下面的命令,可以分析下是否在被CC攻击. 第一条命令: tcpdump -s0 -A -n -i any | grep -o -E '(GET|POST|HEAD) .*' 正常的输出结果类似 ...
- .Net MVC 自定义Action类型,XmlAction,ImageAction等
MVC开发的时候,难免会用到XML格式数据,如果将XML数据当作字符串直接返回给前台,其实这不是真正意义上的xmL,你可以看到ContentType是text/html而非XML类型,这往往会造成前端 ...