All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
net_io.core.NetChannel Maven / Gradle / Ivy
package net_io.core;
import java.io.IOException;
import java.net.ConnectException;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.SocketChannel;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicLong;
import net_io.core.AsyncBaseSocket.EventUpdate;
import net_io.core.AsyncBaseSocket.EventUpdate.MODE;
import net_io.utils.DateUtils;
import net_io.utils.MemoryQueueCache;
import net_io.utils.NetLog;
public class NetChannel {
public enum CONFIG { CONNECT_TIMEOUT, IDLE_TIMEOUT }
/** 默认值:连接超时时间 **/
final public static int DEFAULT_CONNECT_TIMEOUT = 120*1000;
/** 默认值:空闲超时时间 **/
final public static int DEFAULT_IDLE_TIMEOUT = 7200 * 1000; //
/** 通道ID。注册到Pool时更新(累计) **/
protected long ID = 0;
/** 连接超时时间 **/
private long connectTimeout = DEFAULT_CONNECT_TIMEOUT;
/** 空闲超时时间 **/
private long idleTimeout = DEFAULT_IDLE_TIMEOUT;
/** 是否遇到了连接超时 **/
private boolean isConnectTimeout = false;
/** 等待连接完成的信号 **/
private Object waitConnectSingle = new Object();
/** 通道创建时间 **/
private long channelCreateTime = System.currentTimeMillis();
/** 最后活跃时间:产生(或准备)网络IO的时间 **/
private long lastActiveTime = 0;
/** 等待过期后关闭连接的时间 **/
protected volatile long waitExpireTime = 0;
/** 最后的IO异常 **/
protected IOException lastIOException = null;
/** 状态:INIT(初始,刚创建);CONNECT(发起连接);ESTABLISHED(连接已建立)。 **/
public enum Status{INIT, CONNECT, ESTABLISHED, CLOSED}; // CLOSED 从Pool中直接删除。在应用类中,可用来检查状态
/** 发送队列 **/
private ConcurrentLinkedQueue sendQueue = new ConcurrentLinkedQueue();
/** 正在发送中的 ByteBuffer **/
private ByteBuffer sendingBuff = null;
/** 接收缓存区。不为null,则表示正在取数据,且未取满一个包 **/
protected ByteBuffer recvBuff = null;
/** 从Socket读取次数 **/
protected long socketReadCount = 0;
/** 从Socket写入次数 **/
protected long socketWriteCount = 0;
/** 网络通道的状态 **/
protected Status status = Status.INIT;
/** 异步 Socket 管理对象 **/
protected AsyncBaseSocket asyncSocket;
/** 对应到 NIO 中的 Channel **/
protected SocketChannel socket;
protected AsyncBaseSocket.ChannelRegisterHandle channelRegisterHandle = null;
/** 是否为服务器端的 Channel **/
protected boolean serverSide = false;
/** 自增长序列号(调用时有效) **/
private AtomicLong sequenceID = new AtomicLong(0);
/** 响应内容KEY的缓存池 **/
private ConcurrentHashMap responseKeyMap = new ConcurrentHashMap();
/** 通道存储(生命周期:连接建立期间) **/
private ConcurrentHashMap channelStorage = new ConcurrentHashMap();
/** 移除缓存KEY的回调 **/
private RemoveCacheKeyMonitor removeCacheKeyMonitor = new RemoveCacheKeyMonitor();
/** 连接建立事件侦听列表 **/
private ArrayList listConnectEvent = new ArrayList();
/** 系统扫描事件侦听列表 **/
private ArrayList listScanEvent = new ArrayList();
/** 连接关闭事件侦听列表 **/
private ArrayList listCloseEvent = new ArrayList();
/**
* 创建网络通道
* @param asyncSocket 异步Socket管理对象
* @param socketChannel
*/
protected NetChannel(AsyncBaseSocket asyncSocket, SocketChannel socketChannel) {
this.channelCreateTime = System.currentTimeMillis();
this.asyncSocket = asyncSocket;
this.socket = socketChannel;
this.lastIOException = null;
this.connectTimeout = Math.min(this.connectTimeout, asyncSocket.maxConnectTimeout);
this.idleTimeout = Math.min(this.idleTimeout, asyncSocket.maxIdleTimeout);
_setActiveTime(); //设置激活状态
}
/**
* 配置网络通道的参数
* @param type 参数类型
* @param value 值
* @return 返回 this 对象
*/
public NetChannel config(CONFIG type, int value) {
if(type == CONFIG.CONNECT_TIMEOUT) {
connectTimeout = value;
this.connectTimeout = Math.min(this.connectTimeout, this.asyncSocket.maxConnectTimeout);
} else if(type == CONFIG.IDLE_TIMEOUT) {
idleTimeout = value;
this.idleTimeout = Math.min(this.idleTimeout, this.asyncSocket.maxIdleTimeout);
}
return this;
}
/**
* 取得通道ID
*/
public long getChannelID() {
return ID;
}
/**
* 从Socket读取的次数(由NIO底层计数)
*/
public long getSocketReadCount() {
return socketReadCount;
}
/**
* 从Socket写入的次数(由NIO底层计数)
*/
public long getSocketWriteCount() {
return socketWriteCount;
}
/**
* 等待连接完成
* @param timeout 连接超时时间(单位:微秒)
* @return true 连接成功, false连接超时
* @throws ConnectException 连接失败异常
*/
public boolean waitConnect(long timeout) throws ConnectException {
if(status != Status.CONNECT) {
return _returnWaitConnect();
}
connectTimeout = timeout;
synchronized(waitConnectSingle) {
if(status != Status.CONNECT) {
return _returnWaitConnect();
}
try {
waitConnectSingle.wait(timeout);
} catch (InterruptedException e) {
//ignore this exception
}
return _returnWaitConnect();
}
}
protected void _setActiveTime() {
lastActiveTime = System.currentTimeMillis();
if(status == Status.ESTABLISHED) {
waitExpireTime = lastActiveTime + idleTimeout;
} else if(status == Status.CONNECT || status == Status.INIT) {
waitExpireTime = lastActiveTime + connectTimeout;
} else { //CLOSE
waitExpireTime = lastActiveTime - DEFAULT_IDLE_TIMEOUT; //设置过期
}
}
/**
* 返回waitConnect的结果
* @return true 连接成功, false连接超时
* @throws ConnectException 连接失败
*/
private boolean _returnWaitConnect() throws ConnectException {
if(status == Status.ESTABLISHED) {
return true;
}
IOException e = lastIOException;
if(e == null) {
return false;
}
if(e instanceof ConnectException) {
throw (ConnectException) e;
}
return false;
}
/**
* 获取“异步Socket管理对象”
*/
public AsyncBaseSocket getBaseSocket() {
return asyncSocket;
}
/**
* 获取 通道的状态
*/
public Status getChannelStatus() {
return status;
}
/**
* 获取远端网络地址
* 仅支持 Internet Protocol。
* @return 成功返回 InetSocketAddress,除此之外,全部返回null
*/
public InetSocketAddress getRemoteAddress() {
if(socket != null) {
try {
SocketAddress address = socket.getRemoteAddress();
if(address instanceof InetSocketAddress) {
return (InetSocketAddress) address;
}
} catch (IOException e) {
//取不到远端网络地址,全部返回null
}
}
return null;
}
/**
* 获取最后活动时间
*/
public long getLastActiveTime() {
return lastActiveTime;
}
/**
* net_io 核心调用:连接中
*/
protected void _gotoConnect() {
status = Status.CONNECT;
_setActiveTime();
}
/**
* net_io 核心调用:已建立连接
*/
protected void _gotoEstablished() {
status = Status.ESTABLISHED;
_setActiveTime();
synchronized(waitConnectSingle) {
waitConnectSingle.notifyAll();
}
processEvent(listConnectEvent); //处理连接建立事件
}
/**
* 是否为服务器端的Channel
* @return true or false
*/
public boolean isServerSide() {
return serverSide;
}
/**
* 是否活跃中的Channel(连接建立状态)
* @return true of false
*/
public boolean isActive() {
return (status == Status.ESTABLISHED);
}
public int getLocalPort() {
return socket.socket().getLocalPort();
}
public long getCreateTime() {
return channelCreateTime;
}
/** 核心调用:获取发送缓存 **/
protected ByteBuffer _getSendBuff() {
_setActiveTime(); //设置激活状态
if(sendingBuff == null || sendingBuff.hasRemaining() == false) {
sendingBuff = sendQueue.poll();
}
return sendingBuff;
}
public void send(ByteBuffer buff) throws IOException {
// buff.rewind();
_send(buff);
}
public void send(ByteArray data) throws IOException {
// buff.rewind();
send(data.getByteBuffer());
}
/**
* 暂停读取
* @throws IOException
*/
public void pauseRead() throws IOException {
SelectionKey key = socket.keyFor(asyncSocket.selector);
if(key == null) {
throw new IOException("Can not find the SelectionKey.");
}
key.interestOps(key.interestOps() & ~SelectionKey.OP_READ); //监听写事件
}
/**
* 重新读取
* @throws IOException
*/
public void resumeRead() throws IOException {
SelectionKey key = socket.keyFor(asyncSocket.selector);
if(key == null) {
throw new IOException("Can not find the SelectionKey.");
}
key.interestOps(key.interestOps() | SelectionKey.OP_READ); //监听写事件
}
public int getSendQueueSize() {
return sendQueue.size();
}
protected void _send(ByteBuffer buff) throws IOException {
_setActiveTime();
int size = buff.limit() - buff.position();
ByteBuffer sendBuff = ByteBuffer.allocate(size);
if(size > 0) {
System.arraycopy(buff.array(), buff.position(), sendBuff.array(), 0, size);
sendBuff.limit(size);
}
sendQueue.offer(sendBuff);
SelectionKey key = socket.keyFor(asyncSocket.selector);
if(key == null) {
return; //发起连接后,立即发消息,导致 channel 未注册
//TODO: 其它错误检查,处理
//throw new IOException("channel is not open. Socket is registered: "+socket.isRegistered()+", is open: "+socket.isOpen());
}
//key.interestOps(key.interestOps() | SelectionKey.OP_WRITE); //监听写事件
asyncSocket.eventUpdateQueue.offer(new EventUpdate(key, SelectionKey.OP_WRITE, MODE.OR));
asyncSocket.selector.wakeup();
}
/**
* 关闭连接
*/
public void close() {
if(status == Status.CLOSED) {
return; //Channel已经关闭,则直接退出
}
status = Status.CLOSED; //设置CLOSE状态1
asyncSocket.closeChannel(this);
processEvent(listCloseEvent); //处理关闭事件
}
/**
* 关闭连接
*/
public void closeAndSendRemaining() {
if(status == Status.CLOSED) {
return; //Channel已经关闭,则直接退出
}
status = Status.CLOSED; //设置CLOSE状态2
//取消读取时间
SelectionKey key = socket.keyFor(asyncSocket.selector);
if(key == null) {
return; //发起连接后,立即发消息,导致 channel 未注册
//TODO: 其它错误检查,处理
//throw new IOException("channel is not open. Socket is registered: "+socket.isRegistered()+", is open: "+socket.isOpen());
}
// if(sendQueue.isEmpty() && (sendingBuff == null || sendingBuff.hasRemaining() == false)) {
// asyncSocket.closeChannel(this);
// return;
// }
//去除读取监听事件
key.interestOps(key.interestOps() & ~SelectionKey.OP_READ);
final NetChannel that = this;
new Thread() {
public void run() {
for(int i=0; i<600; i++) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
NetLog.logDebug(e);
}
if(sendQueue.isEmpty() && (sendingBuff == null || sendingBuff.hasRemaining() == false)) {
break;
}
}
asyncSocket.closeChannel(that);
}
}.start();
}
/**
* 连接被关闭了。由底层调用
*/
protected void _doClosed() {
status = Status.CLOSED; //设置CLOSE状态3
//通知连接结束
synchronized(waitConnectSingle) {
waitConnectSingle.notifyAll();
}
//清空发送队列
sendQueue.clear();
//清空接收缓存
if(responseKeyMap.size() > 0) {
MemoryQueueCache memoryCache = asyncSocket.channelPool.memoryCache;
for(String cacheKey : responseKeyMap.keySet()) {
responseKeyMap.remove(cacheKey);
memoryCache.remove(cacheKey);
synchronized(cacheKey) {
cacheKey.notifyAll();
}
}
}
}
public String toString() {
StringBuffer sb = new StringBuffer();
sb.append("ID: "+ID);
sb.append(", Status: "+status);
if(socket != null) {
sb.append(", Channel: "+socket.socket().getRemoteSocketAddress());
}
sb.append(", ActiveTime: "+DateUtils.getDateTime(new Date(lastActiveTime)));
return sb.toString();
}
public boolean isConnectTimeout() {
return isConnectTimeout;
}
/**
* 生成并返回,自增长序列号(int类型,可以为负数)
*/
public int generateSequenceID() {
return (int) sequenceID.incrementAndGet();
}
/** 从通道存储中取出数据 **/
public Object getChannelStorage(String key) {
return channelStorage.get(key);
}
/** 保存到通道存储中 **/
public void setChannelStorage(String key, Object value) {
channelStorage.put(key, value);
}
/** 是否存在于通道存储中 **/
public boolean containsChannelStorage(String key) {
return channelStorage.containsKey(key);
}
/** 删除通道存储中的数据 **/
public void removeChannelStorage(String key) {
channelStorage.remove(key);
}
/**
* 获取响应包
* @param sequenceID 序列号
* @param timeout 超时时间(单位:ms)
* @return sequenceID的响应内容
*/
public Object fetchResponse(int sequenceID, long timeout) throws IOException {
String cacheKey = getResponseCacheKey(sequenceID); //缓存KEY
MemoryQueueCache memoryCache = asyncSocket.channelPool.memoryCache;
Object data = memoryCache.get(cacheKey);
if(data == null && timeout > 0) {
synchronized(cacheKey) {
try {
cacheKey.wait(timeout);
} catch (InterruptedException e) {
NetLog.logDebug(e); //ignore...
}
}
data = memoryCache.get(cacheKey);
}
//取到数据后,清除缓存
if(data != null) {
memoryCache.remove(cacheKey);
responseKeyMap.remove(cacheKey);
} else { //未取到数据,检查错误类型
if(timeout > 0) {
throw new IOException("Receive timeout.");
}
if(this.status == Status.CLOSED) {
throw new IOException("The connection is closed.");
}
}
return data;
}
/**
* 保存响应包
* @param sequenceID 序列号
* @param data sequenceID的响应内容
*/
public void putResponse(int sequenceID, Object data) {
if(data == null) {
throw new NullPointerException("[NetChannel.putResponse] data is null.");
}
String cacheKey = getResponseCacheKey(sequenceID); //缓存KEY
//先加入当前类的缓存KEY,因为memoryCache通过定时器移除KEY时,会有一次回调。
responseKeyMap.put(cacheKey, new Long(System.currentTimeMillis()));
//加入缓存
asyncSocket.channelPool.memoryCache.set(cacheKey, data, removeCacheKeyMonitor);
//通知接收线程,读取数据
synchronized(cacheKey) {
cacheKey.notifyAll();
}
}
/** 接收缓存KEY(支持同步锁) **/
private String getResponseCacheKey(int sequenceID) {
StringBuilder build = new StringBuilder();
build.append("NET-IO-CHANNEL-");
build.append(String.valueOf(ID));
build.append("-");
build.append(String.valueOf(sequenceID));
build.append("#");
return build.toString().intern();
}
/** 核心调用:剩余的存活时间(过期关闭) **/
protected long _checkRemainingAliveTime(long currentTime) {
processEvent(listScanEvent); //扫描事件
return waitExpireTime - currentTime;
}
public void listenConnectEvent(Event event) {
addEvent(listConnectEvent, event);
}
public void listenScanEvent(Event event) {
addEvent(listScanEvent, event);
}
public void listenCloseEvent(Event event) {
addEvent(listCloseEvent, event);
}
private void addEvent(List listEvent, Event event) {
synchronized(listEvent) {
listEvent.add(event);
}
}
private void processEvent(List listEvent) {
if(listEvent.isEmpty()) {
return; //忽略并发导致的延迟更新size的问题
}
synchronized(listEvent) {
for(Event event : listEvent) {
if(event.handle(this) == false) {
break;
}
}
}
}
/** NetChannel的事件 **/
public static interface Event {
/**
* 事件处理方法
* @param channel 触发事件的NetChannel
* @return true继续下一条规则,false当前规则运行完毕后退出
*/
public boolean handle(NetChannel channel);
}
private class RemoveCacheKeyMonitor implements MemoryQueueCache.RemoveMonitor {
@Override
public void callback(String removeKey) {
if(responseKeyMap.remove(removeKey) != null) {
synchronized(removeKey) {
removeKey.notifyAll();
}
}
}
}
// /**
// * 根据 NetChannel 的状态,自动检查处理:CONNECT
// */
// protected void checkConnectStatus() {
// long minTime = System.currentTimeMillis() - connectTimeout;
// if(minTime > lastActiveTime) {
// if(NetLog.LOG_LEVEL >= NetLog.DEBUG) {
// NetLog.logDebug("Close Connect Timeout Channel: "+this);
// }
// isConnectTimeout = true;
// asyncSocket.closeChannel(this);
// }
// }
//
// /**
// * 根据 NetChannel 的状态,自动检查处理:ESTABLISHED
// */
// protected void checkEstablishedStatus() {
// long minTime = System.currentTimeMillis() - idleTimeout;
// if(minTime > lastActiveTime) {
// if(NetLog.LOG_LEVEL >= NetLog.DEBUG) {
// NetLog.logDebug("Close Idle Timeout Channel: "+this);
// }
// asyncSocket.closeChannel(this);
// } else {
// //TODO 清除接收区缓存
// }
// }
//
}