package net.xdevelop.nioserver;
import java.util.List;
import java.util.LinkedList;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.channels.Selector;
import java.nio.channels.SelectionKey;
import java.util.Iterator;
import java.util.Set;
import net.xdevelop.nioserver.event.ServerListener;
/**
* <p>Title: 主控服务线程</p>
* @author starboy
* @version 1.0
*/
public class Server implements Runnable {
private static List wpool = new LinkedList(); // 回应池
private static Selector selector;
private ServerSocketChannel sschannel;
private InetSocketAddress address;
protected Notifier notifier;
private int port;
/**
* 创建主控服务线程
* @param port 服务端口
* @throws java.lang.Exception
*/
private static int MAX_THREADS = 4;
public Server(int port) throws Exception {
this.port = port;
// 获取事件触发器
notifier = Notifier.getNotifier();
// 创建读写线程池
for (int i = 0; i < MAX_THREADS; i++) {
Thread r = new Reader();
Thread w = new Writer();
r.start();
w.start();
}
// 创建无阻塞网络套接
selector = Selector.open();
sschannel = ServerSocketChannel.open();
sschannel.configureBlocking(false);
address = new InetSocketAddress(port);
ServerSocket ss = sschannel.socket();
ss.bind(address);
sschannel.register(selector, SelectionKey.OP_ACCEPT);
}
public void run() {
System.out.println("Server started ...");
System.out.println("Server listening on port: " + port);
// 监听
while (true) {
try {
int num = 0;
num = selector.select();
if (num > 0) {
Set selectedKeys = selector.selectedKeys();
Iterator it = selectedKeys.iterator();
while (it.hasNext()) {
SelectionKey key = (SelectionKey) it.next();
it.remove();
// 处理IO事件
if ( (key.readyOps() & SelectionKey.OP_ACCEPT) == SelectionKey.OP_ACCEPT) {
// Accept the new connection
ServerSocketChannel ssc = (ServerSocketChannel) key.channel();
notifier.fireOnAccept();
SocketChannel sc = ssc.accept();
sc.configureBlocking(false);
// 触发接受连接事件
Request request = new Request(sc);
notifier.fireOnAccepted(request);
// 注册读操作,以进行下一步的读操作
sc.register(selector, SelectionKey.OP_READ, request);
}
else if ( (key.readyOps() & SelectionKey.OP_READ) == SelectionKey.OP_READ ) {
Reader.processRequest(key); // 提交读服务线程读取客户端数据
key.cancel();
}
else if ( (key.readyOps() & SelectionKey.OP_WRITE) == SelectionKey.OP_WRITE ) {
Writer.processRequest(key); // 提交写服务线程向客户端发送回应数据
key.cancel();
}
}
}
else {
addRegister(); // 在Selector中注册新的写通道
}
}
catch (Exception e) {
notifier.fireOnError("Error occured in Server: " + e.getMessage());
continue;
}
}
}
/**
* 添加新的通道注册
*/
private void addRegister() {
synchronized (wpool) {
while (!wpool.isEmpty()) {
SelectionKey key = (SelectionKey) wpool.remove(0);
SocketChannel schannel = (SocketChannel)key.channel();
try {
schannel.register(selector, SelectionKey.OP_WRITE, key.attachment());
}
catch (Exception e) {
try {
schannel.finishConnect();
schannel.close();
schannel.socket().close();
notifier.fireOnClosed((Request)key.attachment());
}
catch (Exception e1) {}
notifier.fireOnError("Error occured in addRegister: " + e.getMessage());
}
}
}
}
/**
* 提交新的客户端写请求于主服务线程的回应池中
*/
public static void processWriteRequest(SelectionKey key) {
synchronized (wpool) {
wpool.add(wpool.size(), key);
wpool.notifyAll();
}
selector.wakeup(); // 解除selector的阻塞状态,以便注册新的通道
}
}
没有合适的资源?快使用搜索试试~ 我知道了~
基于事件的 NIO 多线程服务器(源码)
共13个文件
java:13个
4星 · 超过85%的资源 需积分: 10 7 下载量 107 浏览量
2013-07-22
17:43:19
上传
评论
收藏 10KB ZIP 举报
温馨提示
基于事件的 NIO 多线程服务器(源码) 可以根据博客中的描述对照学习
资源推荐
资源详情
资源评论
收起资源包目录
nioserver.zip (13个子文件)
src
net
xdevelop
nioserver
Server.java 5KB
Request.java 1KB
Notifier.java 2KB
ServerHandler.java 1KB
Reader.java 3KB
event
ServerListener.java 1KB
EventAdapter.java 729B
Response.java 689B
Writer.java 2KB
timeserver
LogHandler.java 548B
TimeHandler.java 1KB
Start.java 820B
Client.java 1KB
共 13 条
- 1
资源评论
- woshipark2013-12-31不错,谢谢分享,适合入门
- Kenneth__Lee2014-03-26一般,注释太少
小桥
- 粉丝: 75
- 资源: 29
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
- 基于STM32F103C8T6单片机蓄电池在线监测系统主板硬件(原理图+PCB)工程文件.zip
- mysql大纲资料.txt
- c++大纲资料.txt
- 效率工具bat脚本实现日志提取
- MyBatis 中动态 SQL 的示例
- STM8L101F3P6单片机+CC1100模块433M遥控器设计硬件(原理图+PCB)工程文件.zip
- 上传下载铁人下载系统 Liuxing 1.0-liuxing1.0.rar
- 南京邮电大学数学实验实力雄厚,凭借其优秀的师资力量、丰富的实践教学资源和卓越的科研成果,成为国内一流的数学实验教学和科研基地
- 【火爆朋友圈的今天吃什么源码 v1.0】随机的为用户带来每一天的用餐选择和推荐.rar
- MPU6050中文版数据手册
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功