如下程序是简单实现了一个极其简单的WEB服务器,用来监听某个端口,接受客户端输入输出信息。

但这个程序有一个致命的问题就是连接会长时间阻塞

于是BIO版本出现了,改成了  一个连接 一个线程来处理请求

此时主程序会立即返回并等待下一个连接。但这个程序的问题是 每次一个连接 需要单独创建一个线程,服务器线程资源是优先的,而且1000个连接 有可能有效的读、写事件更少,所以NIO做法是一个

归类问题:

  1. 每个请求都需要创建独立的线程,与对应的客户端进行数据处理。
  2. 当并发数大时,需要创建大量线程来处理连接,系统资源占用较大。
  3. 连接建立后,如果当前线程暂时没有数据可读,则当前线程会一直阻塞在 Read 操作上,造成线程资源浪费

NIO

下面附上一段NIO简易代码说明问题

1)
监听的事件有
OP_ACCEPT: 接收就绪,ServerSocketChannel使用的
OP_READ: 读取就绪,socketChannel使用
OP_WRITE: 写入就绪,socketChannel使用
OP_CONNECT: 连接就绪,socketChannel使用 2)
public static void main(String[] args) throws IOException {
ServerSocketChannel ssc = ServerSocketChannel.open();//管道型ServerSocket
ssc.socket().bind(new InetSocketAddress(Constant.HOST, Constant.PORT));
ssc.configureBlocking(false);//设置非阻塞
System.out.println(" NIO single server started, listening on :" + ssc.getLocalAddress()); //Selector选择器可以监听多个Channel通道感兴趣的事情(read、write、accept(服务端接收)、connect,实现一个线程管理多个Channel,节省线程切换上下文的资源消耗。Selector只能管理非阻塞的通道,FileChannel是阻塞的,无法管理 Selector selector = Selector.open();
ssc.register(selector, SelectionKey.OP_ACCEPT);// 就绪事件【在建立好的管道上,注册关心的事件】
while(true) {
selector.select();
Set<SelectionKey> keys = selector.selectedKeys();
Iterator<SelectionKey> it = keys.iterator();
while(it.hasNext()) {
SelectionKey key = it.next();
it.remove();//处理的事件,必须删除
handle(key);
}
}
} /**
* SocketChannel:从TCP网络中读取或者写入数据。
* ServerSocketChannel:允许你监听来自TCP的连接,就像服务器一样。每一个连接都会有一个SocketChannel产生。
*/
private static void handle(SelectionKey key) throws IOException {
if(key.isAcceptable()) {
ServerSocketChannel ssc = (ServerSocketChannel) key.channel();
/**
*

如果此通道处于非阻塞模式,则此方法将立即返回NULL
*否则它将无限期阻塞,直到有新连接可用为止
*或发生I / O错误。

@return 返回新创建的连接socketChannel

或者返回NULL如果此通道处于非阻塞模式)
*并且无法接受任何连接

*/

                SocketChannel sc = ssc.accept();
sc.configureBlocking(false);//设置非阻塞
sc.register(key.selector(), SelectionKey.OP_READ );//[可读]在建立好的管道上,注册关心的事件
} else if (key.isReadable()) { //flip
SocketChannel sc = null;
sc = (SocketChannel)key.channel();
ByteBuffer buffer = ByteBuffer.allocate(512);
buffer.clear();
int len = sc.read(buffer);
if(len != -1) {
System.out.println("[" +Thread.currentThread().getName()+"] recv :"+ new String(buffer.array(), 0, len));
}
ByteBuffer bufferToWrite = ByteBuffer.wrap("HelloClient".getBytes());
sc.write(bufferToWrite);
}
}

最新文章

  1. caffe的python接口学习(4):mnist实例---手写数字识别
  2. 转: Hibernate HQL查询 插入 更新(update)实例
  3. Yii URL
  4. boost线程的问题:
  5. 【C#】构造函数的特点
  6. python实现不可修改的常量
  7. hdu 5545 The Battle of Guandu spfa最短路
  8. Cocos Studio1.5.0.1开发学习笔记(一)
  9. 数据存储(三)--JSON数据处理
  10. tomcat 部署web项目异常
  11. liunx下search文件内容的几种方式
  12. token的时限多长才合适?
  13. Vim编辑器的注释,解注,删除与恢复
  14. Spring AOP (一)
  15. Ubuntu环境下配置darknet
  16. Unity3D之Mesh(四)绘制多边形
  17. 解决Postgres无法连接的问题
  18. 重启HA集群NameNode无缘无故挂掉
  19. jdk1.6空轮询Bug的原因及解决方法
  20. 【LOJ】#2270. 「SDOI2017」天才黑客

热门文章

  1. 百度地图AK密钥申请
  2. 【论文笔记】 Popularity Bias in Dynamic Recommendation
  3. 【九度OJ】题目1065:输出梯形 解题报告
  4. 【LeetCode】73. Set Matrix Zeroes 解题报告(Python & C++)
  5. 【LeetCode】427. Construct Quad Tree 解题报告(Python)
  6. BestCoder Round #66 (div.2)B GTW likes gt
  7. freeswitch APR-UTIL库线程池实现分析
  8. C++基础之参数重载
  9. 物联网大赛 - Android学习笔记(三)Android 事件处理
  10. STM32零基础入门教程