/**********************************************************\ | | | hprose | | | | Official WebSite: http://www.hprose.com/ | | http://www.hprose.org/ | | | \**********************************************************/ /**********************************************************\ * * * Connector.java * * * * hprose Connector class for Java. * * * * LastModified: Sep 19, 2016 * * Author: Ma Bingyao <andot@hprose.com> * * * \**********************************************************/ package hprose.net; import java.io.IOException; import java.net.InetSocketAddress; import java.net.URI; import java.net.URISyntaxException; import java.nio.channels.ClosedChannelException; import java.nio.channels.ClosedSelectorException; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.nio.channels.SocketChannel; import java.util.Iterator; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.atomic.AtomicInteger; public final class Connector extends Thread { protected final AtomicInteger size = new AtomicInteger(0); private final Selector selector; private final ReactorGroup reactor; private final Queue<Connection> queue = new ConcurrentLinkedQueue<Connection>(); public Connector(int reactorThreads) throws IOException { this.selector = Selector.open(); this.reactor = new ReactorGroup(reactorThreads); } @Override public final void run() { reactor.start(); try { while (!isInterrupted()) { try { process(); dispatch(); } catch (IOException e) {} } } catch (ClosedSelectorException e) {} reactor.close(); } public final void close() { try { selector.close(); } catch (IOException e) {} } private void process() { for (;;) { final Connection conn = queue.poll(); if (conn == null) { break; } try { conn.connect(selector); } catch (ClosedChannelException e) { conn.close(); } catch (IOException e) { conn.close(); } } } private void dispatch() throws IOException { int n = selector.select(); if (n == 0) return; Iterator<SelectionKey> it = selector.selectedKeys().iterator(); while (it.hasNext()) { SelectionKey key = it.next(); it.remove(); if (key.isConnectable()) { connect(key); } } } private void connect(SelectionKey key) throws IOException { final SocketChannel channel = (SocketChannel) key.channel(); if (channel.isConnectionPending()) { channel.finishConnect(); } reactor.register((Connection)key.attachment()); key.cancel(); } private void register(Connection conn) { queue.offer(conn); selector.wakeup(); } public final void create(String uri, ConnectionHandler handler, boolean keepAlive, boolean noDelay) throws IOException { try { URI u = new URI(uri); SocketChannel channel = SocketChannel.open(); InetSocketAddress address = new InetSocketAddress(u.getHost(), u.getPort()); Connection conn = new Connection(channel, handler, address); handler.onConnect(conn); channel.configureBlocking(false); channel.socket().setReuseAddress(true); channel.socket().setKeepAlive(keepAlive); channel.socket().setTcpNoDelay(noDelay); register(conn); } catch (URISyntaxException e) { throw new IOException(e.getMessage()); } } }