网络通讯技术java NIO
http://ifeve.com/java-nio-all/
产生背景
NIO(Non-blocking IO)非阻塞的IO模型
传统 客户端-服务端 每次新建公路 用完后公路没了
现在 客户端-服务端 建立一个高速公路,每次都在这个公路上,
端口资源只占用一个。
阻塞:面向数据而言
同步:IO事件而晏
--现有IO模型
BIO-同步 jdk1.4之前 数据缓冲区(水龙头下水桶)
NIO-同步 jak1.4以后 非阻塞IO linux的多路复用技术,轮询机制
1 nio增加缓冲池。
2 高速通道Channel
3 线程模型方面改进 accept() 线程创建不断排队
4 增加多路复用机制 selector (一个线程+selector)
一个线程一个任务->任务注册selector,源码一个线程去轮训selector。
得到selectorKey一些就绪通道集合(底层源码)
epoll取代了传统select实现,没有最大的句柄限制。
AIO-异步 jdk1.7以后 把IO读写交给操作系统 学习linux epoll模式
[b]
NIO服务类介绍:
ServerSocketChannel 配合我们高速通道 Channel
Selector
SelectorKey
手写一个服务通信框架(NIO)并发
package com.hailong.yu.dongnaoxuexi;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
/**
* 通信服务类
* 接受上线客户端
* @param args
*/
public class NIOService {
private ServerSocketChannel server;
int port =8080;
//注册器
private Selector selector;
//数据缓冲区 接收
ByteBuffer recBuffer = ByteBuffer.allocate(1024);
ByteBuffer sendBuffer = ByteBuffer.allocate(1024);
//中间缓存消息
private Map<SelectionKey, String> sesionMaps =new HashMap<SelectionKey, String>();
public NIOService(int port) throws IOException {
this.port = port;
server = ServerSocketChannel.open();
// 服务类绑定监听端口
server.socket().bind(new InetSocketAddress(port));
// server要设置为非阻塞,执行任务时(在线程调度任务时),对方没有准备好数据,
// 我们做其他任务,准备好后selector(selector中间调度器通知),key事件得到通知,再继续做此任务。
server.configureBlocking(false);// 默认是阻塞
selector = selector.open();
// 服务类和注册管家联系起来,服务类接收
server.register(selector, SelectionKey.OP_ACCEPT);
System.out.println("NIO服务已经启动,监听端口是"+this.port);
}
public void listenter() throws IOException{
while(true) {
int eventCount = selector.select();
if(eventCount == 0) {
continue;
}
// 这里就等于线程轮训selector拿到事件类型标签
Set<SelectionKey> selectionKeySet = selector.selectedKeys();
final Iterator<SelectionKey> iterator = selectionKeySet.iterator();
while(iterator.hasNext()) {
// 处理进程
process(iterator.next());
}
}
}
private void process(SelectionKey selectionKey) {
SocketChannel channel = null;
try {
if(selectionKey.isValid() && selectionKey.isAcceptable()) {
// 通过判断key 拿到链接进来channel
channel =server.accept();
channel.configureBlocking(false);
channel.register(selector, SelectionKey.OP_READ);
} else if(selectionKey.isValid() && selectionKey.isReadable()) {
//读取客服端请求
recBuffer.clear();
channel = (SocketChannel)selectionKey.channel();
int len = channel.read(recBuffer);
if(len>0) {
String msg = new String(recBuffer.array(),0,len);
//聊天记录 维护key 缓存信息结构
sesionMaps.put(selectionKey, msg);
System.out.println("获取客户端发送来的信息:" +Thread.currentThread().getId()+ ","+ msg);
channel.register(selector, SelectionKey.OP_WRITE);
}
} else if(selectionKey.isValid() && selectionKey.isWritable()) {
if(!sesionMaps.containsKey(selectionKey)) {
return;
}
channel = (SocketChannel)selectionKey.channel();
//响应客服端请求
sendBuffer.clear();
sendBuffer.put(new String(sesionMaps.get(selectionKey)+",您好,处理完成").getBytes());
//切换操作位
sendBuffer.flip();
channel.write(sendBuffer);
channel.register(selector, SelectionKey.OP_READ);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
selectionKey.cancel();
try {
channel.socket().close();
channel.close();
return;
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
try {
new NIOService(8080).listenter();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
package com.hailong.yu.dongnaoxuexi;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Scanner;
import java.util.Set;
public class NIOClient {
SocketChannel client;
InetSocketAddress serverAddress = new InetSocketAddress("locallhost", 8080);
Selector selector;
//数据缓冲区 接收
ByteBuffer recBuffer = ByteBuffer.allocate(1024);
ByteBuffer sendBuffer = ByteBuffer.allocate(1024);
public NIOClient() throws IOException {
client = SocketChannel.open();
client.configureBlocking(false);
client.connect(serverAddress);
selector = Selector.open();
client.register(selector, SelectionKey.OP_CONNECT);
}
public void session() throws IOException {
if(client.isConnectionPending()) {
client.finishConnect();
client.register(selector, SelectionKey.OP_WRITE);
System.out.println("已经连接到服务器,可以在控制台登记了");
}
Scanner scan = new Scanner(System.in);
while(scan.hasNextLine()) {
//键盘输入内容
String name = scan.nextLine();
if("".equals(name)) {
continue;
}
if("finish".equals(name)) {
System.exit(0);
}
process(name);
}
}
private void process(String name) throws IOException {
boolean waitHelp = true;
Iterator<SelectionKey> iterator = null;
Set<SelectionKey> keys = null;
while(waitHelp) {
int readys = selector.select();
//如果没有客人,继续轮训
if(readys ==0){
continue;
}
keys = selector.selectedKeys();
iterator = keys.iterator();
try {
while(iterator.hasNext()) {
SelectionKey key = iterator.next();
if(key.isValid() && key.isWritable()) {
sendBuffer.clear();
sendBuffer.put(name.getBytes());
sendBuffer.flip();
client.write(sendBuffer);
client.register(selector, SelectionKey.OP_READ);
} else if(key.isValid() && key.isReadable()) {
recBuffer.clear();
int len = client.read(recBuffer);
if(len>0) {
recBuffer.flip();
System.out.println("服务器反馈消息"+new String(recBuffer.array(),0,len));
client.register(selector, SelectionKey.OP_WRITE);
waitHelp = false;
}
}
iterator.remove();
}
} catch(IOException e) {
((SelectionKey) keys).cancel();
client.socket().close();
client.close();
return;
}
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
}
}
--NIO原理解读[/b]
1 多路复用(channel通道)
2 轮询机制(seletor选择器) 注册行为 给客户一个排队号(selectionKey),
处理完后,回收牌号
3 selectionKey
相当于时间标签
4 buffer数据缓冲区
5 NIO常用api
channel:
服务端:serverSocketChannel ,BIO:serverSocket
客户端:socketChannel ,BIO:socket
open();//建立公司修起来
channel.regist(selector, 注册的标识)
5.1.选择器 seclector
选择器有open方法 open(); 开始营业
selectKeys();//获取当前已经注册的所有牌号信息
5.2.缓冲区 Buffer
put() //往缓冲区里面写数据
get() //读数据
flip() //切换读写模式
clear() //清空缓冲区
5.3.牌号 seletionKey
isAccptable() //是否可以接受客户链接
isConctionable() //是否已经链接
isReadable() //缓冲区是否可读
isWriteabel() //是否可写
--java AIO简介
服务端: AsynchronousServerSocketChannel
客户端: AsynchronousServerChannel
CompletionMandler:通知程序,IO操作是否成功,还是失败。
--具体代码
分享到:
相关推荐
Java NIO,全称为Non-Blocking Input/Output(非阻塞输入/输出),是Java平台中用于替代标准I/O(BIO)模型的一种新机制。NIO在Java 1.4版本引入,提供了更高效的数据处理和通道通信方式,特别适用于高并发、大数据...
### Java NIO 处理超大数据文件的知识点详解 #### 一、Java NIO简介 Java NIO(New IO)是Java平台上的新输入/输出流API,它提供了与传统IO(即Java IO)不同的数据处理方式。NIO在Java 1.4版本引入,并在后续版本...
Java NIO,全称为Non-Blocking Input/Output(非阻塞输入/输出),是Java标准库提供的一种替代传统的I/O模型的新技术。自Java 1.4版本引入NIO后,它为Java开发者提供了更高效的数据传输方式,尤其是在处理大量并发...
在Java编程领域,NIO(New IO)是一个重要的特性,它是Java 1.4版本引入的,用于替代标准的IO API。NIO提供了一种非阻塞I/O操作的方式,特别适用于处理大量的并发连接,例如在文件传输、网络通信等场景。本主题...
在Java编程领域,NIO(New Input/Output)是一个重要的概念,它提供了非阻塞I/O操作的能力,相比传统的BIO(Blocking I/O),在处理大量并发连接时表现出更高的效率和性能。本项目"基于nio的简易聊天室"旨在通过NIO...
赠送jar包:xnio-nio-3.8.0.Final.jar; 赠送原API文档:xnio-nio-3.8.0.Final-javadoc.jar; 赠送源代码:xnio-nio-3.8.0.Final-sources.jar; 赠送Maven依赖信息文件:xnio-nio-3.8.0.Final.pom; 包含翻译后的API...
它基于Java NIO API,利用其非阻塞I/O特性,可以同时处理大量连接,尤其适合于高并发的网络环境。HttpCore NIO 4.3版是对该框架的进一步优化和完善,增强了对HTTP/1.1协议的支持,同时保持了良好的兼容性和稳定性。 ...
《NIO与Socket编程技术指南》是一本深入探讨Java NIO(New Input/Output)和Socket编程的专业书籍,由高洪岩撰写。本书主要针对Java开发者,旨在帮助他们理解和掌握这两种在开发网络应用中至关重要的技术。 Java ...
### Java NIO 详细教程知识点解析 #### 一、Java NIO 概述 Java NIO(New IO)是Java平台提供的一种新的IO操作模式,它首次出现在Java 1.4版本中,并在后续版本中不断完善。Java NIO 的设计目的是为了克服传统Java ...
**NIO(New Input/Output)是Java编程语言中用于替代标准I/O(BIO,Blocking I/O)的一组API,它提供了非阻塞式的I/O操作方式,极大地提升了Java在处理I/O密集型应用时的性能。NIO在Java 1.4版本中被引入,之后在...
本项目"基于Spring Boot + NIO实现的电商平台见证宝服务"旨在利用Spring Boot的便捷性与NIO(非阻塞I/O)的效率,来打造一个高效、稳定且可扩展的服务。下面将详细阐述其中涉及的关键技术点。 首先,Spring Boot是...
Java作为一门广泛使用的开发语言,提供了多种I/O(Input/Output)通信模型,包括传统的阻塞I/O(BIO)、非阻塞I/O(NIO)以及异步I/O(AIO)。这些通信模型在不同的场景下有着各自的优势,理解和掌握它们对于优化...
设计思想: 每次通过nio读取字节到 fbb中 然后对fbb自己中的内容进行行判断即 10 回车 13 行号 0 文件结束 这样字节的判断,然后 返回行 如果 到达 fbb的结尾 还没有结束,就再通过nio读取一段字节,继续处理...
### Java NIO (New IO) 详解 #### 1. 引言 在Java的世界里,I/O(Input/Output)操作是程序与外部环境进行交互的重要方式之一。随着技术的发展,传统I/O模型逐渐显露出一些局限性,特别是在处理高并发场景下,其...
Java NIO(New IO)是Java 1.4版本引入的一个新模块,它提供了一种不同于传统IO(基于字节流和字符流)的I/O操作方式。传统的IO模型是阻塞式的,而NIO的核心特点是非阻塞,这使得在处理大量并发I/O请求时更为高效。...
赠送jar包:httpcore-nio-4.4.6.jar 赠送原API文档:httpcore-nio-4.4.6-javadoc.jar 赠送源代码:httpcore-nio-4.4.6-sources.jar 包含翻译后的API文档:httpcore-nio-4.4.6-javadoc-API文档-中文(简体)版.zip ...
Java NIO(Non-blocking Input/Output)是一种在Java中处理I/O操作的新方式,相比于传统的BIO(Blocking I/O),NIO提供了更高效的数据传输能力,尤其适合于高并发、低延迟的网络应用,如聊天服务器。在这个场景下,...