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编程 假如所有可用 ...
随机推荐
- 全局变量重复定义,fatal error LNK1169: 找到一个或多个多重定义的符号
1.在GlobeValue.h中定义了一个变量: char gl_UID[256]; 2.在b.cpp和e.cpp中分别引用GlobeValue.h,并且使用gl_UID的全局变量, 结果出现:fat ...
- ansible-palybook剧本
1 ansible基础知识部分补充 1.1 ansible软件特点: · 可以实现批量管理 · 可以实现批量部署 · ad-hoc(批量执行命令)---针对临时性的操作 ansible clsn -m ...
- 你知道JQuery中的事件冒泡吗,他是怎么执行的,如何来停止冒泡事件?
事件冒泡 首先需要知道什么是事件冒泡? 事件冒泡是从里面的往外面开始触发的,就是点击子节点,会向上触发父节点,祖先节点的点击事件 demo: <html xmlns="http://w ...
- 在Python中使用正则表达式去掉字符串里的html标签
有时候会获得一些带html标签的字符串,需要把html标签去掉,获得干净的字符串,这时候可以使用正则表达式. 代码如下: import re htmeString = '''<ul id=&qu ...
- 类的特殊方法"__new__"详解
上代码! class A: def __new__(cls, *args, **kwargs): obj = super().__new__(cls) print("__new__ &quo ...
- Python爬虫爬取豆瓣电影之数据提取值xpath和lxml模块
工具:Python 3.6.5.PyCharm开发工具.Windows 10 操作系统.谷歌浏览器 目的:爬取豆瓣电影排行榜中电影的title.链接地址.图片.评价人数.评分等 网址:https:// ...
- 学习RUNOOB.COM进度二
MongoDB 概念解析 SQL术语/概念 MongoDB术语/概念 解释/说明 database database 数据库 table collection 数据库表/集合 row document ...
- HDOJ 1176 免费馅饼(完全背包)
参考:https://blog.csdn.net/hhu1506010220/article/details/52369785 https://blog.csdn.net/enjoying_scien ...
- 理解Canvas像素边界
大家看下面的例子 var context = document.getElementById('canvas').getContext('2d'); context.lineWidth = 1; co ...
- Java8新特性(三)——Optional类、接口方法与新时间日期API
一.Optional容器类 这是一个可以为null的容器对象.如果值存在则isPresent()方法会返回true,调用get()方法会返回该对象. 查看结构图可以看到有如下常用方法: of(T)—— ...