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