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