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的差异.它们的使用场景,以及它们怎样影响您的代 ...
随机推荐
- node的http请求
//node的http服务 'use strict' var http = require('http') var server = http.createServer(function (reque ...
- Eclipse 使用 SVN 插件后修改用户方法汇总
http://blog.csdn.net/ShaneLooLi/article/details/50994005 ******************************************* ...
- c#:使用using关键字自动释放资源未必一定就会有明显好处
public string ToXML() { string strXml = string.Empty; try { MemoryStream ms = new MemoryStream(); Xm ...
- 【Python】打印object对象
print (object .__dict__) print (dir(object))
- java基础篇---I/O技术(一)
对于任何程序设计语言而言,输入输出(I/O)系统都是比较复杂的而且还是比较核心的.在java.io.包中提供了相关的API. java中流的概念划分 流的方向: 输入流:数据源到程序(inputStr ...
- [转]SpringMVC单文件上传、多文件上传、文件列表显示、文件下载
一.新建一个Web工程,导入相关的包 springmvc的包+commons-fileupload.jar+connom-io.jar+commons-logging,jar+jstl.jar+sta ...
- centos7永久更改主机名
操作环境: [root@bogon ~]# uname -a Linux #localhost.localdomain 3.10.0-514.el7.centos.plus.i686 #1 SMP W ...
- 解密SVM系列(二):SVM的理论基础
上节我们探讨了关于拉格朗日乘子和KKT条件.这为后面SVM求解奠定基础,本节希望通俗的细说一下原理部分. 一个简单的二分类问题例如以下图: 我们希望找到一个决策面使得两类分开.这个决策面一般表示就是W ...
- css部分样式资料
1. css字体 Lato,"Helvetica Neue","Segoe UI",Helvetica,Arial,sans-serif
- <[长期赢利:股票价值投资方法]>读书笔记
书在这里 风险是因为不够专业 在股市里,要不断拓宽自己的眼界 投资如长跑,贵在坚持 长线为主,短线为辅:重视选股,减少盲目:耐心等待,春天回来 除了要与银行利息比以外,还要了解当时股票的平均市盈率,再 ...