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