NIO--2-代码
package com.study.nio; 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; public class NIOServer {
private static int port = 9995; //端口 // 1.第一个是服务
private static ServerSocketChannel server; // 2.第二个是多路复用器
private static Selector selector; // 3.第三个就是缓冲区buffer
// 信息接收
ByteBuffer rcBuffer = ByteBuffer.allocate(1024);
// 信息写出
ByteBuffer sendBuffer = ByteBuffer.allocate(1024); // 4.维护一个事件标签集合,和selector配合使用
Map<SelectionKey,String> sessionMsg = new HashMap<SelectionKey,String>(); // 初始化
public NIOServer() throws IOException{
server = ServerSocketChannel.open(); // 打开服务端,服务端临听端口
server.socket().bind(new InetSocketAddress(port)); //
server.configureBlocking(false); //设置为非阻塞,默认是true
selector = Selector.open(); //实例化多路复用器 //server注册上多路复用器之后,多路复用器才会为server工作,实现一个server为成千上万个client工作
//selector和事件标签Selectionkey是一起应用的,第一次服务器,是接受,Accept
server.register(selector, SelectionKey.OP_ACCEPT);
System.out.println("NIO服务器已启动,且监听的端口是" + port); //this.port范围加大
} // 监听请求方法
public void listen() throws IOException{
while(true){
// 进来就是通过多路复用器selector,来看是否有注册事件
int eventCount = selector.select(); // 已注册事件数量
if(eventCount == 0){
// selector继续轮询,NIO的内部机制就是不断轮询注册到selector上面的多个channel
continue;
} // 拿到事件集合,SelectorKey的作用就是获取这些就绪通道的集合
Set<SelectionKey> keys = selector.selectedKeys(); //迭代
Iterator<SelectionKey> iterator = keys.iterator();
while(iterator.hasNext()){
SelectionKey key = iterator.next(); //这个事件就是客户端的一个读或者写
process(key); //处理事件
//处理完后,事件移出集合
iterator.remove();
}
}
} // 处理客户端事件
private void process(SelectionKey key) {
// 处理客户端请求,定义客户端对象
SocketChannel client = null;
try { // 判断key是否是有效的
if(key.isValid() && key.isAcceptable()){
client = server.accept(); //接收一个客户端
client.configureBlocking(false); //设置为非阻塞
client.register(selector , SelectionKey.OP_READ); //读取客户端请求,事件标签类型改为读取 } else if(key.isValid() && key.isReadable()){ //是否是可读的
// 读到缓冲区
rcBuffer.clear();
client = (SocketChannel)key.channel(); // 拿到客户端通道
int len = client.read(rcBuffer); //读取的长度
if(len > 0){ //读到内容
String msg = new String(rcBuffer.array() , 0 ,len);
System.out.println("服务端收到msg:"+msg);
sessionMsg.put(key, msg);
// 告诉selector,已读完,下次可以写数据
client.register(selector, SelectionKey.OP_WRITE);
}
}else if(key.isValid() && key.isWritable()){
if(!sessionMsg.containsKey(key)){ //是否有消息需要回
return;
} //回复消息
client = (SocketChannel)key.channel(); // 拿到客户端通道
sendBuffer.clear();
sendBuffer.put(new String(sessionMsg.get(key)+ "你好,你的请求已完成").getBytes()); //设置读取位
sendBuffer.flip(); // 缓冲区的内容写出去
client.write(sendBuffer); // 再次注册入selector
client.register(selector, SelectionKey.OP_READ);
}
} catch (IOException e) {
try { //读取key事件时,遇到客户端异常下线,不会引起异常
key.cancel();
client.socket().close();
client.close();
} catch (IOException e1) {
e1.printStackTrace();
}
} } public static void main(String[] args) {
try {
NIOServer server = new NIOServer();
server.listen();
} catch (IOException e) {
e.printStackTrace();
}
}
}
CLIENT
package com.study.nio; 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; public class NIOClient {
private static int port = 9995; //端口 // 1.第一个是服务
private static ServerSocketChannel clientC; // 2.第二个是多路复用器
private static Selector selector; // 3.第三个就是缓冲区buffer
// 信息接收
ByteBuffer rcBuffer = ByteBuffer.allocate(1024);
// 信息写出
ByteBuffer sendBuffer = ByteBuffer.allocate(1024); // 4.维护一个事件标签集合,和selector配合使用
Map<SelectionKey,String> sessionMsg = new HashMap<SelectionKey,String>(); // 初始化
public NIOClient() throws IOException{
clientC = ServerSocketChannel.open(); // 打开服务端,服务端临听端口
clientC.socket().bind(new InetSocketAddress(port)); //
clientC.configureBlocking(false); //设置为非阻塞,默认是true
selector = Selector.open(); //实例化多路复用器 //server注册上多路复用器之后,多路复用器才会为server工作,实现一个server为成千上万个client工作
//selector和事件标签Selectionkey是一起应用的,第一次服务器,是接受,Accept
clientC.register(selector, SelectionKey.OP_ACCEPT);
System.out.println("NIO服务器已启动,且监听的端口是" + port); //this.port范围加大
} // 监听请求方法
public void listen() throws IOException{
while(true){
// 进来就是通过多路复用器selector,来看是否有注册事件
int eventCount = selector.select(); // 已注册事件数量
if(eventCount == 0){
// selector继续轮询,NIO的内部机制就是不断轮询注册到selector上面的多个channel
continue;
} // 拿到事件集合,SelectorKey的作用就是获取这些就绪通道的集合
Set<SelectionKey> keys = selector.selectedKeys(); //迭代
Iterator<SelectionKey> iterator = keys.iterator();
while(iterator.hasNext()){
SelectionKey key = iterator.next(); //这个事件就是客户端的一个读或者写
process(key); //处理事件
//处理完后,事件移出集合
iterator.remove();
}
}
} // 处理客户端事件
private void process(SelectionKey key) {
// 处理客户端请求,定义客户端对象
SocketChannel client = null;
try { // 判断key是否是有效的
if(key.isConnectable()){
client = (SocketChannel)key.channel(); // 拿到客户端通道
client.configureBlocking(false); //设置为非阻塞
client.register(selector , SelectionKey.OP_READ); //读取客户端请求,事件标签类型改为读取 } else if(key.isValid() && key.isReadable()){ //是否是可读的
// 读到缓冲区
rcBuffer.clear();
client = (SocketChannel)key.channel(); // 拿到客户端通道
int len = client.read(rcBuffer); //读取的长度
if(len > 0){ //读到内容
String msg = new String(rcBuffer.array() , 0 ,len);
sessionMsg.put(key, msg);
// 告诉selector,已读完,下次可以写数据
client.register(selector, SelectionKey.OP_WRITE);
}
}else if(key.isValid() && key.isWritable()){
if(!sessionMsg.containsKey(key)){ //是否有消息需要回
return;
} //回复消息
client = (SocketChannel)key.channel(); // 拿到客户端通道
sendBuffer.clear();
sendBuffer.put(new String(sessionMsg.get(key)+ "你好,你的请求已完成").getBytes()); //设置读取位
sendBuffer.flip(); // 缓冲区的内容写出去
client.write(sendBuffer); // 再次注册入selector
client.register(selector, SelectionKey.OP_READ);
}
} catch (IOException e) {
try { //读取key事件时,遇到客户端异常下线,不会引起异常
key.cancel();
client.socket().close();
client.close();
} catch (IOException e1) {
e1.printStackTrace();
}
} } public static void main(String[] args) {
try {
NIOServer server = new NIOServer();
server.listen();
} catch (IOException e) {
e.printStackTrace();
}
}
}
NIO--2-代码的更多相关文章
- Java基础知识强化之IO流笔记72:NIO之 NIO核心组件(NIO使用代码示例)
1.Java NIO 由以下几个核心部分组成: Channels(通道) Buffers(缓冲区) Selectors(选择器) 虽然Java NIO 中除此之外还有很多类和组件,Channel,Bu ...
- Java NIO 学习笔记
为了防止无良网站的爬虫抓取文章,特此标识,转载请注明文章出处.LaplaceDemon/SJQ. http://www.cnblogs.com/shijiaqi1066/p/3344148.html ...
- nio简介
上一篇 Java I/O演进与Linux网络I/O模型 一.传统BIO java传统bio编程概念: http://www.cnblogs.com/carl10086/p/6034563.html# ...
- 掌握NIO,程序人生
就像新IO为java带来的革新那样,让我们也开启一段新的程序人生. 关键字:NIO,BIO,伪IO,AIO,多路复用选择器,通道,缓冲区,jdk研究,回调函数,高并发 java.nio 概述 历史背景 ...
- Netty5序章之BIO NIO AIO演变
Netty5序章之BIO NIO AIO演变 Netty是一个提供异步事件驱动的网络应用框架,用以快速开发高性能.高可靠的网络服务器和客户端程序.Netty简化了网络程序的开发,是很多框架和公司都在使 ...
- Java NIO之网络编程
最近在研究Java NIO和netty,曾经一度感觉很吃力,根本原因还是对操作系统.TCP/IP.socket编程的理解不到位. 不禁感叹,还是当初逃的课太多. 假如上天给我一次机会,能够再回到意气风 ...
- 操作系统层面聊聊BIO,NIO和AIO (epoll)
BIO 有了Block的定义,就可以讨论BIO和NIO了.BIO是Blocking IO的意思.在类似于网络中进行read, write, connect一类的系统调用时会被卡住. 举个例子,当用re ...
- Netty序章之BIO NIO AIO演变
Netty序章之BIO NIO AIO演变 Netty是一个提供异步事件驱动的网络应用框架,用以快速开发高性能.高可靠的网络服务器和客户端程序.Netty简化了网络程序的开发,是很多框架和公司都在使用 ...
- day 4 Socket 和 NIO Netty
Scoket通信--------这是一个例子,可以在这个例子的基础上进行相应的拓展,核心也是在多线程任务上进行修改 package cn.itcast.bigdata.socket; import j ...
- Java NIO Socket编程实例
各I/O模型优缺点 BIO通信模型 BIO主要的问题在于每当有一个新的客户端请求接入时,服务端必须创建一个新的线程处理新接入的客户端链路,一个线程只能处理一个客户端连接 线程池I/O编程 假如所有可用 ...
随机推荐
- 前行记录 - NOIP2018游记
NOIP2018游记 - 前行记录 NOIP2018 完跪……滚回学校考半期 QwQ 这篇不是题解 awa ,题解之后会发布的,毕竟我还没有AC呢 又及……G2020 陌路笙歌 - 再见(╯▽╰) 感 ...
- vuex重置所有state(可定制)
在正式场景中我们经常遇到一个问题,就是登出页面或其他操作的时候,我们需要重置所有的vuex,让其变为初始状态,那么,就涉及到了多种方法:1.页面刷新: window.location.reload() ...
- CSS3--j惊艳到你的新前端
一.css3的选择器 1. 父子选择器 直接关系 .box>.com 2. 兄弟选择器 相邻关系 .box+.com <span>hello</span> <p&g ...
- python练习笔记
python练习笔记,装饰器.定制方法生成特定的类 # -*- coding: utf-8 -*- def catch_exception(func): def wrap(self, *args, * ...
- 做 JAVA 开发,怎能不用 IDEA!
用了 IDEA,感觉不错.决定弃用 Eclipse 入门教程: www.cnblogs.com/yangyquin/p/5285272.html
- vue笔记 介绍及安装 一
Vue.js 是什么 Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架.与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用.Vue 的核心库只关注视图层, ...
- ruby File类
类方法 路径相关: File.basename(filename <, suffix>) -> string返回给定文件名 filename 的最后一部分.如果有 suffix 参数 ...
- 《史上最简单的MySQL教程》系列分享专栏
<史上最简单的MySQL教程>系列分享专栏 <史上最简单的MySQL教程>已整理成PDF文档,点击可直接下载至本地查阅https://www.webfalse.com/read ...
- WHERE条件中or与union引起的全表扫描的问题
说起数据库的SQL语句执行效率的问题,就不得不提where条件语句中的or(逻辑或)引起的全表扫描问题,从而导致效率下降. 在以往绝大多数的资料中,大多数人的建议是使用 union 代替 or ,以解 ...
- C语言Windows程序开发—TextOut函数介绍【第02天】
(一)TextOut函数的参数介绍: BOOL TextOut ( //如果函数调用成功,返回TRUE,否则,返回FALSE HDC hdc, //用于显示字符串的控件ID int nXStart, ...