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.Date;
import java.util.Iterator;
import java.util.Set;
/**
* ProductName:BIO_TimeServer
* Date:2015/10/1
* Author:crixusshen
* Coding is also a art !
*/
public class MultiplexerTimeServer implements Runnable {
// 定义多路复用器,单线程接入多客户端
private Selector selector;
// 定义父管道,监听所有客户端连接
private ServerSocketChannel serverSocketChannel;
private volatile boolean stop;
/**
* 初始化多路复用器,绑定监听端口
*
* @param port 监听端口
*/
public MultiplexerTimeServer(int port){
try {
// 创建selector多路复用器
selector = Selector.open();
// 打开ServerSocketChannel父管道,监听所有客户端的连接
serverSocketChannel = ServerSocketChannel.open();
// 设置非阻塞
serverSocketChannel.configureBlocking(false);
serverSocketChannel.socket().bind(new InetSocketAddress(port), 1024);
// 将父管道注册到多路上,并监听accept事件
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
System.out.println("The time server is start in port:" + port);
} catch (IOException e) {
e.printStackTrace();
}
}
public void stop(){
this.stop = true;
}
@Override
public void run() {
while (!stop){
try {
selector.select(1000);
// 多路轮询发现已就绪的KEY
Set<SelectionKey> selectionKeys = selector.selectedKeys();
Iterator<SelectionKey> it = selectionKeys.iterator();
SelectionKey key = null;
while (it.hasNext()){
key = it.next();
// ???????????????????????????
it.remove();
try {
handleInput(key);
}catch (Exception e){
if(key != null){
key.cancel();
if(key.channel() != null){
key.channel().close();
}
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
if(selector != null){
try {
selector.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
private void handleInput(SelectionKey key) throws IOException{
if(key.isValid()){
// 处理新接入的请求消息
if(key.isAcceptable()){
// 接受新的connection
ServerSocketChannel ssc = (ServerSocketChannel)key.channel();
// 建立三次握手,并建立物理链路
SocketChannel sc = ssc.accept();
sc.configureBlocking(false);
// 增加新的connection到多路复用器selector上
sc.register(selector, SelectionKey.OP_READ);
}
// 如果connection已经建立连接则进行读操作
if(key.isReadable()){
// 读取数据
SocketChannel sc = (SocketChannel)key.channel();
// 建立1k缓冲区
ByteBuffer readBuffer = ByteBuffer.allocate(1024);
// 将报文读入缓冲区
int readBytes = sc.read(readBuffer);
if(readBytes > 0){
readBuffer.flip();
byte[] bytes = new byte[readBuffer.remaining()];
// 将缓冲区中的数据读入内存区中
readBuffer.get(bytes);
String body = new String(bytes, "UTF-8");
System.out.println("The time server receive order:" + body);
String currentTime = "QUERY TIME ORDER".equalsIgnoreCase(body) ? new Date(System.currentTimeMillis()).toString() : "BAD ORDER";
// 将数据反馈给请求客户端
doWrite(sc, currentTime);
}
else if(readBytes < 0){
// 对端链路关闭
key.cancel();
sc.close();
}
// 读到0字节,忽略
else{
}
}
}
}
private void doWrite(SocketChannel channel, String response) throws IOException{
if(response != null && response.trim().length() > 0){
byte[] bytes = response.getBytes();
ByteBuffer writeBufer = ByteBuffer.allocate(bytes.length);
writeBufer.put(bytes);
writeBufer.flip();
channel.write(writeBufer);
}
}
}
BIO,NIO,AIO实现的demo
4星 · 超过85%的资源 需积分: 50 181 浏览量
2015-10-04
09:20:40
上传
评论
收藏 60KB RAR 举报
szw297118147
- 粉丝: 1
- 资源: 7
最新资源
- Screenshot_20240427_031602.jpg
- 网页PDF_2024年04月26日 23-46-14_QQ浏览器网页保存_QQ浏览器转格式(6).docx
- 直接插入排序,冒泡排序,直接选择排序.zip
- 在排序2的基础上,再次对快排进行优化,其次增加快排非递归,归并排序,归并排序非递归版.zip
- 实现了7种排序算法.三种复杂度排序.三种nlogn复杂度排序(堆排序,归并排序,快速排序)一种线性复杂度的排序.zip
- 冒泡排序 直接选择排序 直接插入排序 随机快速排序 归并排序 堆排序.zip
- 课设-内部排序算法比较 包括冒泡排序、直接插入排序、简单选择排序、快速排序、希尔排序、归并排序和堆排序.zip
- Python排序算法.zip
- C语言实现直接插入排序、希尔排序、选择排序、冒泡排序、堆排序、快速排序、归并排序、计数排序,并带图详解.zip
- 常用工具集参考用于图像等数据处理
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈