All Downloads are FREE. Search and download functionalities are using the official Maven repository.

cn.tom.transport.nio.Selectors Maven / Gradle / Ivy

The newest version!
package cn.tom.transport.nio;


import java.io.Closeable;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.StandardSocketOptions;
import java.nio.channels.SelectableChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.concurrent.atomic.AtomicInteger;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import cn.tom.kit.ThreadPool;
import cn.tom.transport.IoAdaptor;

public class Selectors implements Closeable {
	private static final Logger log = LoggerFactory.getLogger(Selectors.class); 
	
	private int selectCnt = ThreadPool.cpuCoreCount;
	private SelectorThread[] selectors;
	private AtomicInteger selectorIndex = new AtomicInteger(0);
	private String selectorName  = "cocook-nio-Selector";
	
	protected volatile boolean started = false;  //直接读内存
	private IoAdaptor serverIoAdaptor;
	
	private void init() throws IOException{
		this.selectors = new SelectorThread[this.selectCnt];
		for(int i=0;i=this.selectCnt){
			throw new IllegalArgumentException("Selector index should >=0 and <"+this.selectCnt);
		}
		return this.selectors[index];
	}
	
	public SelectorThread nextSelector(){
		int nextIdx = this.selectorIndex.getAndIncrement()%this.selectCnt;
		if(nextIdx < 0){
			this.selectorIndex.set(0);
			nextIdx = 0;
		} 
		return this.selectors[nextIdx];
	}

	public void registerChannel(SelectableChannel channel, int ops) throws IOException{
		this.nextSelector().registerChannel(channel, ops);
	}
	
	public void registerSession(int ops, NioSession sess) throws IOException{
		if(sess.selectors() != this){
			throw new IOException("Unmatched Dispatcher");
		}
	
		this.nextSelector().registerSession(ops, sess);
	}
	
	public SelectorThread getSelector(SelectionKey key){
		for(SelectorThread e : this.selectors){
			if(key.selector() == e.selector){
				return e;
			}
		}
		return null;
	}
	
	public synchronized void start() {
		if (this.started) {
			return;
		}
		try {
			this.init();
		} catch (IOException e) {
			log.error(e.getMessage(), e);
			return;
		}
		this.started = true;
		for (SelectorThread selector : this.selectors) {
			selector.setDaemon(false);
			selector.start();
		} 
	}
	
	public synchronized void stop() {
		if (!this.started)
			return;

		this.started = false;
		for (SelectorThread selector : this.selectors) {
			selector.interrupt();
			selector = null;
		}
		log.info("{}(SelecctorCount={}) stopped", this.selectorName, this.selectCnt);
	}
	
	public void close() throws IOException {
		this.stop();
	}
	
	public boolean isStarted(){
		return this.started;
	}
	
	public int getSelectCnt() {
		return selectCnt;
	}

	public void setSelectCnt(int selectCnt) {
		this.selectCnt = selectCnt;
	}

	public IoAdaptor serverIoAdaptor(){
		return this.serverIoAdaptor; 
	}
	public Selectors serverIoAdaptor(IoAdaptor serverIoAdaptor){ 
		if(this.serverIoAdaptor != null){
			throw new IllegalStateException("Server IoAdaptor already exists");
		}
		this.serverIoAdaptor = serverIoAdaptor;
		return this;
	}
	
	public ServerSocketChannel registerServerChannel(String host, int port) throws IOException{
		ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
    	serverSocketChannel.configureBlocking(false);
    	serverSocketChannel.socket().bind(new InetSocketAddress(host, port)); 
    	serverSocketChannel.setOption(StandardSocketOptions.SO_REUSEADDR, true);
    	serverSocketChannel.setOption(StandardSocketOptions.SO_RCVBUF, 1 * 1024 * 1024);
    	this.registerChannel(serverSocketChannel, SelectionKey.OP_ACCEPT);
    	return serverSocketChannel;
	}
	
	
	public NioSession registerClientChannel(String host, int port, IoAdaptor ioAdaptor) throws IOException{
		SocketChannel channel = SocketChannel.open();
    	channel.configureBlocking(false);
    	channel.connect(new InetSocketAddress(host, port)); 
    	NioSession session = new NioSession(this, channel, ioAdaptor);
    	session.setServer(false);
    	this.registerSession(SelectionKey.OP_CONNECT, session);
    	session.waitToConnect(20000);  //等待连接释放
    	return session;
	}
	
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy