session類圖java
// 建立服務器監聽 IoAcceptor acceptor = new NioSocketAcceptor(); // 設置buffer的長度 acceptor.getSessionConfig().setReadBufferSize(2048); // 設置鏈接超時時間 acceptor.getSessionConfig().setIdleTime(IdleStatus.BOTH_IDLE, 10);
session作爲一個鏈接的具體對象,緩存當前鏈接用戶的一些信息。
linux
WriteFuture write(Object message);
WriteFuture write(Object message, SocketAddress destination);
下面着重分析建立過程以及session的狀態緩存
protected NioSession accept(IoProcessor<NioSession> processor, ServerSocketChannel handle) throws Exception { SelectionKey key = handle.keyFor(selector); if ((key == null) || (!key.isValid()) || (!key.isAcceptable())) { return null; } // accept the connection from the client SocketChannel ch = handle.accept(); if (ch == null) { return null; } return new NioSocketSession(this, processor, ch); }
protected final void initSession(IoSession session, IoFuture future, IoSessionInitializer sessionInitializer) { // Update lastIoTime if needed. if (stats.getLastReadTime() == 0) { stats.setLastReadTime(getActivationTime()); } if (stats.getLastWriteTime() == 0) { stats.setLastWriteTime(getActivationTime()); } // Every property but attributeMap should be set now. // Now initialize the attributeMap. The reason why we initialize // the attributeMap at last is to make sure all session properties // such as remoteAddress are provided to IoSessionDataStructureFactory. try { ((AbstractIoSession) session).setAttributeMap(session.getService().getSessionDataStructureFactory() .getAttributeMap(session)); } catch (IoSessionInitializationException e) { throw e; } catch (Exception e) { throw new IoSessionInitializationException("Failed to initialize an attributeMap.", e); } try { ((AbstractIoSession) session).setWriteRequestQueue(session.getService().getSessionDataStructureFactory() .getWriteRequestQueue(session)); } catch (IoSessionInitializationException e) { throw e; } catch (Exception e) { throw new IoSessionInitializationException("Failed to initialize a writeRequestQueue.", e); } if ((future != null) && (future instanceof ConnectFuture)) { // DefaultIoFilterChain will notify the future. (We support ConnectFuture only for now). session.setAttribute(DefaultIoFilterChain.SESSION_CREATED_FUTURE, future); } if (sessionInitializer != null) { sessionInitializer.initializeSession(session, future); } finishSessionInitialization0(session, future); }
private final Queue<S> newSessions = new ConcurrentLinkedQueue<S>(); /** A queue used to store the sessions to be removed */ private final Queue<S> removingSessions = new ConcurrentLinkedQueue<S>(); /** A queue used to store the sessions to be flushed */ private final Queue<S> flushingSessions = new ConcurrentLinkedQueue<S>(); /** * A queue used to store the sessions which have a trafficControl to be * updated */ private final Queue<S> trafficControllingSessions = new ConcurrentLinkedQueue<S>(); /** The processor thread : it handles the incoming messages */ private final AtomicReference<Processor> processorRef = new AtomicReference<Processor>();
private class Processor implements Runnable { public void run() { for (;;) { long t0 = System.currentTimeMillis(); int selected = select(SELECT_TIMEOUT); long t1 = System.currentTimeMillis(); long delta = (t1 - t0); if ((selected == 0) && !wakeupCalled.get() && (delta < 100)) { if (isBrokenConnection()) { wakeupCalled.getAndSet(false); continue; } else { registerNewSelector(); } wakeupCalled.getAndSet(false); continue; } nSessions += handleNewSessions(); updateTrafficMask(); if (selected > 0) { process(); } nSessions -= removeSessions(); } } }
private void process(S session) { // Process Reads if (isReadable(session) && !session.isReadSuspended()) { read(session); } // Process writes if (isWritable(session) && !session.isWriteSuspended()) { // add the session to the queue, if it's not already there if (session.setScheduledForFlush(true)) { flushingSessions.add(session); } } }
acceptor.getSessionConfig().setIdleTime(IdleStatus.BOTH_IDLE, 10);
private static void notifyIdleSession0(IoSession session, long currentTime, long idleTime, IdleStatus status, long lastIoTime) { if ((idleTime > 0) && (lastIoTime != 0) && (currentTime - lastIoTime >= idleTime)) { session.getFilterChain().fireSessionIdle(status); } }
public void fireSessionIdle(IdleStatus status) { session.increaseIdleCount(status, System.currentTimeMillis()); Entry head = this.head; callNextSessionIdle(head, session, status); }