package org.fxc.nio.server;

import java.io.FileInputStream;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.util.Iterator; public class NIOServer {
static int BLOCK = 500*1024; /**
* 处理客户端的内部类,专门负责处理与用户的交互
*/
public class HandleClient {
protected FileChannel channel;
protected ByteBuffer buffer;
String filePath; /**
* 构造函数,文件的管道初始化
* @param filePath
* @throws IOException
*/
public HandleClient(String filePath) throws IOException { //文件的管道
this.channel = new FileInputStream(filePath).getChannel(); //建立缓存
this.buffer = ByteBuffer.allocate(BLOCK);
this.filePath = filePath;
} /**
* 读取文件管道中数据到缓存中
* @return
*/
public ByteBuffer readBlock() {
try { //清除缓冲区的内容,posistion设置为0,limit设置为缓冲的容量大小capacity
buffer.clear(); //读取
int count = channel.read(buffer); //将缓存的中的posistion设置为0,将缓存中的limit设置在原始posistion位置上
buffer.flip();
if (count <= 0)
return null;
} catch (IOException e) {
e.printStackTrace();
}
return buffer;
} /**
* 关闭服务端的文件管道
*/
public void close() {
try {
channel.close();
} catch (IOException e) {
e.printStackTrace();
}
}
} protected Selector selector;
protected String filename = "d:\\film\\hadoop-1.1.2.tar.gz"; // a big file
protected ByteBuffer clientBuffer = ByteBuffer.allocate(BLOCK);
protected CharsetDecoder decoder; //构造服务端口,服务管道等等
public NIOServer(int port) throws IOException {
selector = this.getSelector(port);
Charset charset = Charset.forName("GB2312");
decoder = charset.newDecoder();
} // 获取Selector
//构造服务端口,服务管道等等
protected Selector getSelector(int port) throws IOException {
ServerSocketChannel server = ServerSocketChannel.open();
Selector sel = Selector.open();
server.socket().bind(new InetSocketAddress(port));
server.configureBlocking(false); //刚开始就注册链接事件
server.register(sel, SelectionKey.OP_ACCEPT);
return sel;
} // 服务启动的开始入口
public void listen() {
try {
for (;;) {
//?
selector.select();
Iterator<SelectionKey> iter = selector.selectedKeys()
.iterator();
while (iter.hasNext()) {//首先是最先感兴趣的连接事件
SelectionKey key = iter.next();
//?
iter.remove(); //处理事件
handleKey(key);
}
}
} catch (IOException e) {
e.printStackTrace();
}
} // 处理事件
protected void handleKey(SelectionKey key) throws IOException {
if (key.isAcceptable()) { // 接收请求 //允许网络连接事件
ServerSocketChannel server = (ServerSocketChannel) key.channel();
SocketChannel channel = server.accept();
channel.configureBlocking(false); //网络管道准备处理读事件
channel.register(selector, SelectionKey.OP_READ);
} else if (key.isReadable()) { // 读信息
SocketChannel channel = (SocketChannel) key.channel(); //从客户端读过来的数据块
int count = channel.read(clientBuffer);
if (count > 0) { //读取过来的缓存进行有效分割,posistion设置为0,保证从缓存的有效位置开始读取,limit设置为原先的posistion上
//这样一来从posistion~limit这段缓存数据是有效,可利用的
clientBuffer.flip(); //对客户端缓存块进行编码
CharBuffer charBuffer = decoder.decode(clientBuffer);
System.out.println("Client >>download>>" + charBuffer.toString()); //对网络管道注册写事件
SelectionKey wKey = channel.register(selector,
SelectionKey.OP_WRITE); //将网络管道附着上一个处理类HandleClient,用于处理客户端事件的类
wKey.attach(new HandleClient(charBuffer.toString()));
} else{
//如客户端没有可读事件,关闭管道
channel.close();
} clientBuffer.clear();
} else if (key.isWritable()) { // 写事件
SocketChannel channel = (SocketChannel) key.channel(); //从管道中将附着处理类对象HandleClient取出来
HandleClient handle = (HandleClient) key.attachment(); //读取文件管道,返回数据缓存
ByteBuffer block = handle.readBlock();
if (block != null){
//System.out.println("---"+new String(block.array())); //写给客户端
channel.write(block);
}else {
handle.close();
channel.close();
}
}
} public static void main(String[] args) {
int port = 12345;
try {
NIOServer server = new NIOServer(port);
System.out.println("Listernint on " + port);
while (true) {
server.listen();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}

Nio Server的更多相关文章

  1. Netty3 源代码分析 - NIO server绑定过程分析

    Netty3 源代码分析 - NIO server绑定过程分析      一个框架封装的越好,越利于我们高速的coding.可是却掩盖了非常多的细节和原理.可是源代码可以揭示一切. 服务器端代码在指定 ...

  2. 一段关于java NIO server端接受客户端socket连接;演示了关于channel,selector等组件的整合使用

    public class ReactorDemo { public static void main(String[] args) throws IOException { ServerSocketC ...

  3. Java nio Server端示例

    public class ServerNio { public static void main(String[] args) throws IOException, InterruptedExcep ...

  4. NIO vs. BIO

    性能测试 BIO -- Blocking IO 即阻塞式IO NIO -- Non-Blocking IO, 即非阻塞式IO或异步IO 性能 -- 所谓的性能是指服务器响应客户端的能力,对于服务器我们 ...

  5. 从Jetty、Tomcat和Mina中提炼NIO构架网络服务器的经典模式(三)

    转载 http://blog.csdn.net/cutesource/article/details/6192163 最后我们再看看NIO方面最著名的框架Mina,抛开Mina有关session和处理 ...

  6. java NIO的多路复用及reactor模式【转载】

    关于java的NIO,以下博客总结的比较详细,适合初学者学习(http://ifeve.com/java-nio-all/) 下面的文字转载自:http://www.blogjava.net/hell ...

  7. java nio的一个严重BUG(转)

    这个BUG会在linux上导致cpu 100%,使得nio server/client不可用,具体的详情可以看这里http://bugs.sun.com/bugdatabase/view_bug.do ...

  8. Java NIO的多路复用及reactor

    (from:http://developer.51cto.com/art/201112/306489.htm) 以下描述,为了说明问题,就提提历史(类似的东西,网上一搜一大把,但是希望你能在这里止步, ...

  9. tomcat bio nio apr 模式性能测试

    转自:tomcat bio nio apr 模式性能测试与个人看法 11.11活动当天,服务器负载过大,导致部分页面出现了不可访问的状态.那后来主管就要求调优了,下面是tomcat bio.nio.a ...

随机推荐

  1. URAL 1796. Amusement Park (math)

    1796. Amusement Park Time limit: 1.0 second Memory limit: 64 MB On a sunny Sunday, a group of childr ...

  2. mantis 中文统计报表乱码问题解决办法

    mantis 中文报表乱码问题 1.安装mantisTB 1.2.17:a.安装插件:管理-->插件管理-->安装MantisGraph(Mantis图表 1.0) 插件b.修改配置文件: ...

  3. CGAffineTransformMake(a,b,c,d,tx,ty) 矩阵运算的原理 (转载)

    简记: CGAffineTransformMake(a,b,c,d,tx,ty) ad缩放bc旋转tx,ty位移,基础的2D矩阵 公式 x=ax+cy+tx     y=bx+dy+ty 1.矩阵的基 ...

  4. 通过xib创建控制器

    什么时候才需要使用storyboard,xib,当控制器的view界面是固定死的时候,就考虑用storyboard,xib解决.      目的:让xib描述控制器view          通过xi ...

  5. c++中的const参数,const变量,const指针,const对象,以及const成员函数

    const 是constant 的缩写,“恒定不变”的意思.被const 修饰的东西都受到强制保护,可以预防意外的变动,能提高程序的健壮性.所以很多C++程序设计书籍建议:“Use const whe ...

  6. Module 模式 以及 揭示模式。

    ---恢复内容开始--- Module模式 : 在传统软件工程中为类提供私有和公有封装的方法. 在js中: Module 模式 使用闭包封装 私有状态和组织. 该模式,返回一个公有的API,而其他的一 ...

  7. windows迁移linux问题集锦[ZZ]

    http://blog.csdn.net/m_star_jy_sy/article/details/8482202 1)‘_wcsicmp’在此作用域中尚未声明 #ifdef WIN32#define ...

  8. php代码20个实用技巧 ------ 转发自菜鸟教程

    1.不要实用相对路径 常常会看到: require_once('../../lib/some_class.php'); 该方法有很多缺点:它首先查找指定的php包含路径,然后查找当前目录,因此会检查过 ...

  9. 处理date类型对象的方式

    在jsp中通过key属性映射到编译后jsp页面的name属性,通过model中的 setxxxx()方法将jsp页面通过wdatepicker插件产生的string类型的数据转换为timestamp类 ...

  10. jquery写的tab切换效果 非常简单

    自己写的一款 tab切换效果,比较简单,适合新手 <style type="text/css">*{margin:0; padding:0; font-size:12p ...