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 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 channel.configureBlocking(false);
239
240
241 ServerSocket socket = channel.socket();
242
243 socket.setReuseAddress(isReuseAddress());
244
245 socket.setReceiveBufferSize(getSessionConfig().getReceiveBufferSize());
246
247 socket.bind(localAddress, getBacklog());
248
249 channel.register(selector, SelectionKey.OP_ACCEPT);
250 success = true;
251 } finally {
252 if (!success) {
253 close(channel);
254 }
255 }
256 return channel;
257 }
258
259
260
261
262 @Override
263 protected SocketAddress localAddress(ServerSocketChannel handle)
264 throws Exception {
265 return handle.socket().getLocalSocketAddress();
266 }
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281 @Override
282 protected int select() throws Exception {
283 return selector.select();
284 }
285
286
287
288
289 @Override
290 protected Iterator<ServerSocketChannel> selectedHandles() {
291 return new ServerSocketChannelIterator(selector.selectedKeys());
292 }
293
294
295
296
297 @Override
298 protected void close(ServerSocketChannel handle) throws Exception {
299 SelectionKey key = handle.keyFor(selector);
300
301 if (key != null) {
302 key.cancel();
303 }
304
305 handle.close();
306 }
307
308
309
310
311 @Override
312 protected void wakeup() {
313 selector.wakeup();
314 }
315
316
317
318
319
320 private static class ServerSocketChannelIterator implements Iterator<ServerSocketChannel> {
321
322 private final Iterator<SelectionKey> iterator;
323
324
325
326
327
328
329
330 private ServerSocketChannelIterator(Collection<SelectionKey> selectedKeys) {
331 iterator = selectedKeys.iterator();
332 }
333
334
335
336
337
338
339 public boolean hasNext() {
340 return iterator.hasNext();
341 }
342
343
344
345
346
347
348
349 public ServerSocketChannel next() {
350 SelectionKey key = iterator.next();
351
352 if ( key.isValid() && key.isAcceptable() ) {
353 return (ServerSocketChannel) key.channel();
354 } else {
355 return null;
356 }
357 }
358
359
360
361
362 public void remove() {
363 iterator.remove();
364 }
365 }
366 }