001 002 import java.util.Set; 003 004 import java.io.IOException; 005 import java.net.BindException; 006 import java.net.InetSocketAddress; 007 import java.net.Socket; 008 import java.net.ServerSocket; 009 010 import java.nio.channels.Selector; 011 import java.nio.channels.SelectionKey; 012 import java.nio.channels.ServerSocketChannel; 013 //import java.nio.channels.SocketChannel; 014 015 016 /** 017 * ChannelFactoryNio. 018 * Socket channel factory using java.nio and no Thread. 019 * 020 * Usage: ChannelFactoryNio(port). 021 * @author Heinz Kredel. 022 */ 023 public class ChannelFactoryNio extends Thread { 024 025 /** 026 * default port of socket. 027 */ 028 public final static int DEFAULT_PORT = 4711; 029 030 /** 031 * wait time 500ms. 032 */ 033 public final static int WAIT_TIME = 500; 034 035 /** 036 * port of socket. 037 */ 038 private final int port; 039 040 /** 041 * local selector. 042 */ 043 private Selector selector = null; 044 045 /** 046 * local server key. 047 */ 048 private SelectionKey serverkey = null; 049 050 /** 051 * local server socket channel. 052 */ 053 private ServerSocketChannel server = null; 054 055 056 /** 057 * Constructs a ChannelFactory using Nio. 058 * @param p port. 059 */ 060 public ChannelFactoryNio(int p) { 061 if ( p <= 0 ) { 062 port = DEFAULT_PORT; 063 } else { 064 port = p; 065 } 066 try { 067 selector = Selector.open(); 068 069 server = ServerSocketChannel.open(); 070 server.configureBlocking(false); 071 serverkey = server.register(selector,SelectionKey.OP_ACCEPT); 072 server.socket().bind( new InetSocketAddress(port) ); 073 074 System.out.println("server started on port "+port); 075 } catch (BindException e) { 076 System.out.println(e); 077 serverkey.cancel(); 078 //server.close(); 079 } catch (IOException e) { 080 e.printStackTrace(); 081 } 082 } 083 084 085 /** 086 * Constructs a ChannelFactory Nio. 087 * on the DEFAULT_PORT. 088 */ 089 public ChannelFactoryNio() { 090 this(DEFAULT_PORT); 091 } 092 093 094 /** 095 * Get a new socket channel from a server socket. 096 */ 097 public SocketChannel getChannel() 098 throws IOException { 099 SocketChannel c = null; 100 java.nio.channels.SocketChannel s; 101 while (c == null) { 102 try { 103 System.out.println("waiting for connection"); 104 selector.select(); // blocking 105 106 Set<SelectionKey> keys = selector.selectedKeys(); 107 for ( SelectionKey k: keys ) { 108 if ( k == serverkey ) { 109 if ( k.isAcceptable() ) { // just in case 110 keys.remove(k); 111 s = server.accept(); 112 s.configureBlocking(true); 113 c = new SocketChannel( s.socket() ); 114 System.out.println("connection accepted"); 115 break; // ignore other keys 116 } 117 } else { // ignore client keys 118 selector.wakeup(); 119 } 120 } 121 } catch (IOException e) { 122 System.out.println(e); 123 try { // wait for next client to connect 124 Thread.currentThread().sleep( WAIT_TIME ); 125 } catch (InterruptedException ignored) { } 126 } 127 } 128 return c; 129 } 130 131 132 /** 133 * Get a new socket channel to a given host. 134 * @param h hostname. 135 * @param p port. 136 */ 137 public SocketChannel getChannel(String h, int p) 138 throws IOException { 139 if ( p <= 0 ) { 140 p = port; 141 } 142 SelectionKey clientkey = null; 143 SocketChannel c = null; 144 java.nio.channels.SocketChannel client; 145 System.out.println("connecting to "+h); 146 while (c == null) { 147 try { 148 client = java.nio.channels.SocketChannel.open(); 149 client.configureBlocking(false); 150 clientkey = client.register(selector,SelectionKey.OP_CONNECT); 151 client.connect( new InetSocketAddress(h,p) ); 152 153 selector.select(); // blocking 154 155 Set<SelectionKey> keys = selector.selectedKeys(); 156 for ( SelectionKey k: keys ) { 157 if ( k == clientkey ) { 158 if ( k.isConnectable() ) { // if server ready 159 keys.remove(k); 160 k.cancel(); // required to make blockable 161 client = (java.nio.channels.SocketChannel) k.channel(); 162 client.finishConnect(); 163 client.configureBlocking(true); 164 c = new SocketChannel( client.socket() ); 165 break; // ignore other keys 166 } 167 } else { // ignore server keys 168 selector.wakeup(); 169 } 170 } 171 } catch (IOException e) { 172 System.out.println(e); 173 System.out.println("Server on "+h+" not ready"); 174 try { // wait server ready 175 Thread.currentThread().sleep( WAIT_TIME ); 176 } catch (InterruptedException ignored) { } 177 } 178 } 179 System.out.println("connected"); 180 return c; 181 } 182 183 184 /** 185 * Close the Channel Factory. 186 */ 187 public void close() { 188 try { 189 serverkey.cancel(); 190 selector.close(); 191 server.close(); 192 } catch (IOException e) { 193 e.printStackTrace(); 194 } 195 } 196 197 } 198