`

NIO

    博客分类:
  • IO
 
阅读更多
网络通讯技术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英文高清原版

    Java NIO,全称为Non-Blocking Input/Output(非阻塞输入/输出),是Java平台中用于替代标准I/O(BIO)模型的一种新机制。NIO在Java 1.4版本引入,提供了更高效的数据处理和通道通信方式,特别适用于高并发、大数据...

    java nio 包读取超大数据文件

    ### Java NIO 处理超大数据文件的知识点详解 #### 一、Java NIO简介 Java NIO(New IO)是Java平台上的新输入/输出流API,它提供了与传统IO(即Java IO)不同的数据处理方式。NIO在Java 1.4版本引入,并在后续版本...

    java NIO.zip

    Java NIO,全称为Non-Blocking Input/Output(非阻塞输入/输出),是Java标准库提供的一种替代传统的I/O模型的新技术。自Java 1.4版本引入NIO后,它为Java开发者提供了更高效的数据传输方式,尤其是在处理大量并发...

    基于nio实现的多文件上传源码

    在Java编程领域,NIO(New IO)是一个重要的特性,它是Java 1.4版本引入的,用于替代标准的IO API。NIO提供了一种非阻塞I/O操作的方式,特别适用于处理大量的并发连接,例如在文件传输、网络通信等场景。本主题...

    基于nio的简易聊天室

    在Java编程领域,NIO(New Input/Output)是一个重要的概念,它提供了非阻塞I/O操作的能力,相比传统的BIO(Blocking I/O),在处理大量并发连接时表现出更高的效率和性能。本项目"基于nio的简易聊天室"旨在通过NIO...

    xnio-nio-3.8.0.Final-API文档-中文版.zip

    赠送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...

    httpcore-nio-4.3.jar包

    它基于Java NIO API,利用其非阻塞I/O特性,可以同时处理大量连接,尤其适合于高并发的网络环境。HttpCore NIO 4.3版是对该框架的进一步优化和完善,增强了对HTTP/1.1协议的支持,同时保持了良好的兼容性和稳定性。 ...

    《NIO与Socket编程技术指南》_高洪岩

    《NIO与Socket编程技术指南》是一本深入探讨Java NIO(New Input/Output)和Socket编程的专业书籍,由高洪岩撰写。本书主要针对Java开发者,旨在帮助他们理解和掌握这两种在开发网络应用中至关重要的技术。 Java ...

    java NIO详细教程

    ### Java NIO 详细教程知识点解析 #### 一、Java NIO 概述 Java NIO(New IO)是Java平台提供的一种新的IO操作模式,它首次出现在Java 1.4版本中,并在后续版本中不断完善。Java NIO 的设计目的是为了克服传统Java ...

    NIO 入门.chm,NIO 入门.chm

    **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实现的电商平台见证宝服务"旨在利用Spring Boot的便捷性与NIO(非阻塞I/O)的效率,来打造一个高效、稳定且可扩展的服务。下面将详细阐述其中涉及的关键技术点。 首先,Spring Boot是...

    基于java的BIO、NIO、AIO通讯模型代码实现

    Java作为一门广泛使用的开发语言,提供了多种I/O(Input/Output)通信模型,包括传统的阻塞I/O(BIO)、非阻塞I/O(NIO)以及异步I/O(AIO)。这些通信模型在不同的场景下有着各自的优势,理解和掌握它们对于优化...

    JAVA NIO 按行读取大文件,支持 GB级别

    设计思想: 每次通过nio读取字节到 fbb中 然后对fbb自己中的内容进行行判断即 10 回车 13 行号 0 文件结束 这样字节的判断,然后 返回行 如果 到达 fbb的结尾 还没有结束,就再通过nio读取一段字节,继续处理...

    javaNiO.doc

    ### Java NIO (New IO) 详解 #### 1. 引言 在Java的世界里,I/O(Input/Output)操作是程序与外部环境进行交互的重要方式之一。随着技术的发展,传统I/O模型逐渐显露出一些局限性,特别是在处理高并发场景下,其...

    JAVA-NIO-DEMO

    Java NIO(New IO)是Java 1.4版本引入的一个新模块,它提供了一种不同于传统IO(基于字节流和字符流)的I/O操作方式。传统的IO模型是阻塞式的,而NIO的核心特点是非阻塞,这使得在处理大量并发I/O请求时更为高效。...

    httpcore-nio-4.4.6-API文档-中文版.zip

    赠送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实现多个客户端之间的消息互发,客户端与服务器完整代码

    Java NIO(Non-blocking Input/Output)是一种在Java中处理I/O操作的新方式,相比于传统的BIO(Blocking I/O),NIO提供了更高效的数据传输能力,尤其适合于高并发、低延迟的网络应用,如聊天服务器。在这个场景下,...

Global site tag (gtag.js) - Google Analytics