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的差异.它们的使用场景,以及它们怎样影响您的代 ...
随机推荐
- webstorm的快捷键和zencoding
1.webstorm快捷键: 生成viewport, meta:vp IntelliJ-Idea 的快捷键 Ctrl+/ 或 Ctrl+Shift+/ 注释(// 或者/*…*/ ) Shift+F6 ...
- (转)go语言nsq源码解读二 nsqlookupd、nsqd与nsqadmin
转自:http://www.baiyuxiong.com/?p=886 ---------------------------------------------------------------- ...
- 【转】(六)unity4.6Ugui中文教程文档-------概要-UGUI Animation Integration
原创至上,移步请戳:(六)unity4.6Ugui中文教程文档-------概要-UGUI Animation Integration 5.Animation Integration(动画集成) 动画 ...
- 【Linux技术】linux之configure,pkg-config和PKG_CONFIG_PATH
linux之configure,pkg-config和PKG_CONFIG_PATH 1.初衷 1)前面在装gtk时冒出来一个pkg-config,当时虽然不大清楚它是个什么东西,不过大致了解了下它的 ...
- Asp.Net导出文件名中文乱码
Asp.Net导出word为例,Excel等其他文件也一样 protected void Page_Load(object sender, EventArgs e) {string html = “网 ...
- Python排序dict之list数组
两种办法: 其一lambda表达式: ctx['data'] = sorted(ctx['data'], key=lambda k: k['asrtime'], reverse=True) 其二利用o ...
- css超出一行添加省略号属性:text-overflow和white-space
通过使用text-overflow和white-space属性来使文本在一行内显示,超出则加省略号,添加如下html代码: <p>前端开发博客专注前端开发和技术分享,如果描述超过100像素 ...
- iOS开发:代码通用性以及其规范 第一篇(附带,自定义UITextView\进度条\双表显示\瀑布流 代码设计思路)
在iOS团队开发中,我见过一些人的代码,也修改过他们的代码.有的人的代码写的非常之规范.通用,几乎不用交流,就可以知道如何修改以及在它基础上扩展延生.有的人的代码写的很垃圾,一眼看过去,简直会怀疑自己 ...
- mysql memory engine
前言 刚刚遇到了mysql无法插入数据,报错:the table xxx is full. 查询原因,是xx表使用了memory engine,其中mysql的memory engine中有max_h ...
- JAVA-JSP内置对象之request范围
相关资料:<21天学通Java Web开发> request范围1.在一次请求内有效.2.如果页面从一个页面跳转到另一个页面,那么属性就失效了.3.如果使用服务器端跳转<jsp:fo ...