1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.mina.transport.socket.nio;
21
22 import java.net.InetSocketAddress;
23 import java.net.ServerSocket;
24 import java.net.SocketAddress;
25 import java.nio.channels.SelectionKey;
26 import java.nio.channels.Selector;
27 import java.nio.channels.ServerSocketChannel;
28 import java.nio.channels.SocketChannel;
29 import java.util.Collection;
30 import java.util.Iterator;
31 import java.util.concurrent.Executor;
32
33 import org.apache.mina.core.polling.AbstractPollingIoAcceptor;
34 import org.apache.mina.core.service.IoAcceptor;
35 import org.apache.mina.core.service.IoProcessor;
36 import org.apache.mina.core.service.SimpleIoProcessorPool;
37 import org.apache.mina.core.service.TransportMetadata;
38 import org.apache.mina.transport.socket.DefaultSocketSessionConfig;
39 import org.apache.mina.transport.socket.SocketAcceptor;
40 import org.apache.mina.transport.socket.SocketSessionConfig;
41
42
43
44
45
46
47
48
49 public final class NioSocketAcceptor
50 extends AbstractPollingIoAcceptor<NioSession, ServerSocketChannel>
51 implements SocketAcceptor {
52
53
54
55
56
57 private int backlog = 50;
58
59 private boolean reuseAddress = false;
60
61 private volatile Selector selector;
62
63
64
65
66 public NioSocketAcceptor() {
67 super(new DefaultSocketSessionConfig(), NioProcessor.class);
68 ((DefaultSocketSessionConfig) getSessionConfig()).init(this);
69 }
70
71
72
73
74
75
76
77
78 public NioSocketAcceptor(int processorCount) {
79 super(new DefaultSocketSessionConfig(), NioProcessor.class, processorCount);
80 ((DefaultSocketSessionConfig) getSessionConfig()).init(this);
81 }
82
83
84
85
86
87
88
89 public NioSocketAcceptor(IoProcessor<NioSession> processor) {
90 super(new DefaultSocketSessionConfig(), processor);
91 ((DefaultSocketSessionConfig) getSessionConfig()).init(this);
92 }
93
94
95
96
97
98
99
100
101 public NioSocketAcceptor(Executor executor, IoProcessor<NioSession> processor) {
102 super(new DefaultSocketSessionConfig(), executor, processor);
103 ((DefaultSocketSessionConfig) getSessionConfig()).init(this);
104 }
105
106
107
108
109 @Override
110 protected void init() throws Exception {
111 selector = Selector.open();
112 }
113
114
115
116
117 @Override
118 protected void destroy() throws Exception {
119 if (selector != null) {
120 selector.close();
121 }
122 }
123
124
125
126
127 public TransportMetadata getTransportMetadata() {
128 return NioSocketSession.METADATA;
129 }
130
131
132
133
134 @Override
135 public SocketSessionConfig getSessionConfig() {
136 return (SocketSessionConfig) super.getSessionConfig();
137 }
138
139
140
141
142 @Override
143 public InetSocketAddress getLocalAddress() {
144 return (InetSocketAddress) super.getLocalAddress();
145 }
146
147
148
149
150 @Override
151 public InetSocketAddress getDefaultLocalAddress() {
152 return (InetSocketAddress) super.getDefaultLocalAddress();
153 }
154
155
156
157
158 public void setDefaultLocalAddress(InetSocketAddress localAddress) {
159 setDefaultLocalAddress((SocketAddress) localAddress);
160 }
161
162
163
164
165 public boolean isReuseAddress() {
166 return reuseAddress;
167 }
168
169
170
171
172 public void setReuseAddress(boolean reuseAddress) {
173 synchronized (bindLock) {
174 if (isActive()) {
175 throw new IllegalStateException(
176 "reuseAddress can't be set while the acceptor is bound.");
177 }
178
179 this.reuseAddress = reuseAddress;
180 }
181 }
182
183
184
185
186 public int getBacklog() {
187 return backlog;
188 }
189
190
191
192
193 public void setBacklog(int backlog) {
194 synchronized (bindLock) {
195 if (isActive()) {
196 throw new IllegalStateException(
197 "backlog can't be set while the acceptor is bound.");
198 }
199
200 this.backlog = backlog;
201 }
202 }
203
204
205
206
207 @Override
208 protected NioSession accept(IoProcessor<NioSession> processor,
209 ServerSocketChannel handle) throws Exception {
210
211 SelectionKey key = handle.keyFor(selector);
212
213 if ((key == null) || (!key.isValid()) || (!key.isAcceptable()) ) {
214 return null;
215 }
216
217
218 SocketChannel ch = handle.accept();
219
220 if (ch == null) {
221 return null;
222 }
223
224 return new NioSocketSession(this, processor, ch);
225 }
226
227
228
229
230 @Override
231 protected ServerSocketChannel open(SocketAddress localAddress)
232 throws Exception {
233
234 ServerSocketChannel channel = ServerSocketChannel.open();
235
236 boolean success = false;
237
238 try {
239
240 channel.configureBlocking(false);
241
242
243 ServerSocket socket = channel.socket();
244
245
246 socket.setReuseAddress(isReuseAddress());
247
248
249 socket.setReceiveBufferSize(getSessionConfig().getReceiveBufferSize());
250
251
252 socket.bind(localAddress, getBacklog());
253
254
255 channel.register(selector, SelectionKey.OP_ACCEPT);
256 success = true;
257 } finally {
258 if (!success) {
259 close(channel);
260 }
261 }
262 return channel;
263 }
264
265
266
267
268 @Override
269 protected SocketAddress localAddress(ServerSocketChannel handle)
270 throws Exception {
271 return handle.socket().getLocalSocketAddress();
272 }
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287 @Override
288 protected int select() throws Exception {
289 return selector.select();
290 }
291
292
293
294
295 @Override
296 protected Iterator<ServerSocketChannel> selectedHandles() {
297 return new ServerSocketChannelIterator(selector.selectedKeys());
298 }
299
300
301
302
303 @Override
304 protected void close(ServerSocketChannel handle) throws Exception {
305 SelectionKey key = handle.keyFor(selector);
306
307 if (key != null) {
308 key.cancel();
309 }
310
311 handle.close();
312 }
313
314
315
316
317 @Override
318 protected void wakeup() {
319 selector.wakeup();
320 }
321
322
323
324
325
326 private static class ServerSocketChannelIterator implements Iterator<ServerSocketChannel> {
327
328 private final Iterator<SelectionKey> iterator;
329
330
331
332
333
334
335
336 private ServerSocketChannelIterator(Collection<SelectionKey> selectedKeys) {
337 iterator = selectedKeys.iterator();
338 }
339
340
341
342
343
344
345 public boolean hasNext() {
346 return iterator.hasNext();
347 }
348
349
350
351
352
353
354
355 public ServerSocketChannel next() {
356 SelectionKey key = iterator.next();
357
358 if ( key.isValid() && key.isAcceptable() ) {
359 return (ServerSocketChannel) key.channel();
360 } else {
361 return null;
362 }
363 }
364
365
366
367
368 public void remove() {
369 iterator.remove();
370 }
371 }
372 }