基于NIO和BIO的两种服务器对比
基于BIO的服务器,服务端可能要同时保持几百万个HTTP连接,而这些连接并不是每时每刻都在传输数据,所以这种情况不适合使用BIO的服务器;而且需要保证共享资源的同步与安全,这个实现起来相对复杂。这时候就是基于NIO的服务器出场的时候了。
先来比较下两种服务器的代码
1.NIO实现
public class SelectorServer
{
private static int PORT = 1234; public static void main(String[] args) throws Exception
{
// 先确定端口号
int port = PORT;
if (args != null && args.length > 0)
{
port = Integer.parseInt(args[0]);
}
// 打开一个ServerSocketChannel
ServerSocketChannel ssc = ServerSocketChannel.open();
// 获取ServerSocketChannel绑定的Socket
ServerSocket ss = ssc.socket();
// 设置ServerSocket监听的端口
ss.bind(new InetSocketAddress(port));
// 设置ServerSocketChannel为非阻塞模式
ssc.configureBlocking(false);
// 打开一个选择器
Selector selector = Selector.open();
// 将ServerSocketChannel注册到选择器上去并监听accept事件
ssc.register(selector, SelectionKey.OP_ACCEPT);
while (true)
{
// 这里会发生阻塞,等待就绪的通道
int n = selector.select();
// 没有就绪的通道则什么也不做
if (n == 0)
{
continue;
}
// 获取SelectionKeys上已经就绪的通道的集合
Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
// 遍历每一个Key
while (iterator.hasNext())
{
SelectionKey sk = iterator.next();
// 通道上是否有可接受的连接
if (sk.isAcceptable())
{
ServerSocketChannel ssc1 = (ServerSocketChannel)sk.channel();
SocketChannel sc = ssc1.accept();
sc.configureBlocking(false);
sc.register(selector, SelectionKey.OP_READ);
}
// 通道上是否有数据可读
else if (sk.isReadable())
{
readDataFromSocket(sk);
}
iterator.remove();
}
}
} private static ByteBuffer bb = ByteBuffer.allocate(1024); // 从通道中读取数据
protected static void readDataFromSocket(SelectionKey sk) throws Exception
{
SocketChannel sc = (SocketChannel)sk.channel();
bb.clear();
while (sc.read(bb) > 0)
{
bb.flip();
while (bb.hasRemaining())
{
System.out.print((char)bb.get());
}
System.out.println();
bb.clear();
}
}
}
2.BIO 多线程实现
package com.defonds.socket.begin; import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket; public class Server {
public static final int PORT = 12345;//监听的端口号 public static void main(String[] args) {
System.out.println("服务器启动...\n");
Server server = new Server();
server.init();
} public void init() {
try {
ServerSocket serverSocket = new ServerSocket(PORT);
while (true) {
// 一旦有堵塞, 则表示服务器与客户端获得了连接
Socket client = serverSocket.accept();
// 处理这次连接
new HandlerThread(client);
}
} catch (Exception e) {
System.out.println("服务器异常: " + e.getMessage());
}
} private class HandlerThread implements Runnable {
private Socket socket;
public HandlerThread(Socket client) {
socket = client;
new Thread(this).start();
} public void run() {
try {
// 读取客户端数据
DataInputStream input = new DataInputStream(socket.getInputStream());
String clientInputStr = input.readUTF();//这里要注意和客户端输出流的写方法对应,否则会抛 EOFException
// 处理客户端数据
System.out.println("客户端发过来的内容:" + clientInputStr); // 向客户端回复信息
DataOutputStream out = new DataOutputStream(socket.getOutputStream());
System.out.print("请输入:\t");
// 发送键盘输入的一行
String s = new BufferedReader(new InputStreamReader(System.in)).readLine();
out.writeUTF(s); out.close();
input.close();
} catch (Exception e) {
System.out.println("服务器 run 异常: " + e.getMessage());
} finally {
if (socket != null) {
try {
socket.close();
} catch (Exception e) {
socket = null;
System.out.println("服务端 finally 异常:" + e.getMessage());
}
}
}
}
}
}
基于NIO的服务器相当于把老版本多线程服务器中的read和accept的阻塞时间,都统一集中到了selector.select()里面。当有socket数据过来的时候,selector会选择与当前socket数据对应的一个且已经在其内部注册的channel来执行对应的方法。相当于在老版本多线程服务器中抽象出了一层,这一层就是select方法,这个方法负责接收"任务"以及分发"任务"。

第一种,开多线程可以去接多个请求,防止一个线程的read卡住,无法接收其他客户端的请求。
第二种,把服务提供者全部托管给selector,当有消费任务到来的时候,选择与当前任务适配的服务提供者去提供(而真正的读写操作的阻塞是使用CPU的,真正在"干活",而且这个过程非常快,属于memory copy,带宽通常在1GB/s级别以上,可以理解为基本不耗时)
基于NIO和BIO的两种服务器对比的更多相关文章
- 爬虫2.1-scrapy框架-两种爬虫对比
目录 scrapy框架-两种爬虫对比和大概流程 1. 传统spider爬虫 2. crawl型爬虫 3. 循环页面请求 4. scrapy框架爬虫的大致流程 scrapy框架-两种爬虫对比和大概流程 ...
- 基于Redis的分布式锁两种实现方式
最近有一个竞拍的项目会用到分布式锁,网上查到的结果是有三种途径可以实现.1.数据库锁机制,2.redis的锁,3.zookeeper.考虑到使用mysql实现会在性能这一块会受影响,zookeeper ...
- 基于layPage分页插件浅析两种分页方式
最近在开发过程中经常用到分页,今天挤出些时间来捋一捋自己的经验 在web开发中,一般显示数据列表页时,我们会用到分页控件来显示数据.采用分页一般基于两种不同的需求,一种是数据量不算很大,但是在页面展示 ...
- Java值创建线程的两种方式对比
在Java中创建线程的方式有两种,第一种是直接继承Thead类,另一种是实现Runable接口.那么这两种方式孰优孰劣呢? 采用继承Thead类实现多线程: 优势:编写简单,如果需要访问当前线程,只需 ...
- 多线程实现Thread.Start()与ThreadPool.QueueUserWorkItem两种方式对比
Thread.Start(),ThreadPool.QueueUserWorkItem都是在实现多线程并行编程时常用的方法.两种方式有何异同点,而又该如何取舍? 写一个Demo,分别用两种方式实现.观 ...
- javascript原型继承中的两种方法对比
在实际的项目中,我们通常都是用构造函数来创建一个对象,再将一些常用的方法添加到其原型对象上.最后要么直接实例化该对象,要么将它作为父类,再申明一个对象,继承该父类. 而在继承的时候有两种常用方式,今天 ...
- MySQL两种内核对比
MySQL内核 https://blog.csdn.net/baichoufei90/article/details/83504446 关键字:全文索引 索引外置 两种内核:MyISAM 和InnoD ...
- 【Qt开发】Qt中显示图像的两种方法对比
在Qt中处理图片一般都要用到QImage类,但是QImage的对象不能够直接显示出来,要想能看到图片,初步发现有两种方法. 一.QImage转QPixmap,然后用QLabel::setPixmap( ...
- spring 基于XML和注解的两种事务配置方式
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.sp ...
随机推荐
- Android笔记: fragment简单例子
MainActivity.java public class MainActivity extends Activity { @Override protected void onCreate(Bun ...
- Catalan Number 卡特兰数
内容部分来自以下博客: Cyberspace_TechNode 邀月独斟 一个大叔 表示感谢! Catalan数的引入: 一个长度为2N的序列,里面有N个+1,N个-1 它的任意前缀和均非负,给定N, ...
- poj3876 darts
Darts Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 58 Accepted: 32 Special Judge ...
- Bash 脚本进阶,经典用法及其案例
前言:在linux中,Bash脚本是很基础的知识,大家可能一听脚本感觉很高大上,像小编当初刚开始学一样,感觉会写脚本的都是大神.虽然复杂的脚本是很烧脑,但是,当我们熟练的掌握了其中的用法与技巧,再多加 ...
- 正则语言引擎:一个简单LEX和YACC结合运用的实例
本文先描述了LEX与YACC的书写方法.然后利用LEX与YACC编写了一个简单正则语言的引擎(暂时不支持闭包与或运算),生成的中间语言为C语言. 正则引擎应直接生成NFA或DFA模拟器的输入文件,但在 ...
- [UWP]使用WriteableBitmap创建HSV色轮
1. HSV 1.1 HSV的定义 HSV都是一种将RGB色彩模型中的点在圆柱坐标系中的表示法,这种表示法试图做到比RGB基于笛卡尔坐标系的几何结构更加直观.HSV即色相.饱和度.明度(英语:Hue, ...
- linux命令每日一练:find与rm实现查找并删除目录或文件
linux命令每日一练 linux中find与rm实现查找并删除目录或文件 linux 下用find命令查找文件,rm命令删除文件. 删除指定目录下指定文件 find 要查找的目录名 -name .s ...
- java课程设计——博客作业教学数据分析系统(201521123083 戴志斌)
目录 一.团队课程设计博客链接 二.个人负责模块或任务说明 三.自己的代码提交记录截图 四.自己负责模块或任务详细说明 五.课程设计感想 (题外话,终于可以用markdown建目录) 一.团队课程设计 ...
- 团队作业9——展示博客(Beta版本)
展示博客 1.团队成员的简介和个人博客地址,团队的源码仓库地址. 何琴琴(http://www.cnblogs.com/vviane/): 领导项目进行,协调各队员之间的矛盾合作,负责测试与需求分析. ...
- 团队作业4---第一次项目冲刺(ALpha版本)第一天
一.Daily Scrum Meeting照片 二.燃尽图 三.项目进展 1.界面 完成登录界面 2.功能 完成数据结构设计及数据交互模块代码 完成爬虫博客页面数据采集模块 四.困难与问题 1.因为要 ...