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.common.AbstractPollingIoAcceptor;
33 import org.apache.mina.common.IoAcceptor;
34 import org.apache.mina.common.IoProcessor;
35 import org.apache.mina.common.TransportMetadata;
36 import org.apache.mina.transport.socket.DefaultSocketSessionConfig;
37 import org.apache.mina.transport.socket.SocketAcceptor;
38 import org.apache.mina.transport.socket.SocketSessionConfig;
39
40
41
42
43
44
45
46
47 public final class NioSocketAcceptor
48 extends AbstractPollingIoAcceptor<NioSession, ServerSocketChannel>
49 implements SocketAcceptor {
50
51 private int backlog = 50;
52 private boolean reuseAddress = true;
53
54 private volatile Selector selector;
55
56
57
58
59 public NioSocketAcceptor() {
60 super(new DefaultSocketSessionConfig(), NioProcessor.class);
61 }
62
63 public NioSocketAcceptor(int processorCount) {
64 super(new DefaultSocketSessionConfig(), NioProcessor.class, processorCount);
65 }
66
67 public NioSocketAcceptor(IoProcessor<NioSession> processor) {
68 super(new DefaultSocketSessionConfig(), processor);
69 }
70
71 public NioSocketAcceptor(Executor executor, IoProcessor<NioSession> processor) {
72 super(new DefaultSocketSessionConfig(), executor, processor);
73 }
74
75 @Override
76 protected void init() throws Exception {
77
78 getSessionConfig().setReuseAddress(true);
79 this.selector = Selector.open();
80 }
81
82 @Override
83 protected void destroy() throws Exception {
84 if (selector != null) {
85 selector.close();
86 }
87 }
88
89 public TransportMetadata getTransportMetadata() {
90 return NioSocketSession.METADATA;
91 }
92
93 @Override
94 public SocketSessionConfig getSessionConfig() {
95 return (SocketSessionConfig) super.getSessionConfig();
96 }
97
98 @Override
99 public InetSocketAddress getLocalAddress() {
100 return (InetSocketAddress) super.getLocalAddress();
101 }
102
103 @Override
104 public InetSocketAddress getDefaultLocalAddress() {
105 return (InetSocketAddress) super.getDefaultLocalAddress();
106 }
107
108 public void setDefaultLocalAddress(InetSocketAddress localAddress) {
109 setDefaultLocalAddress((SocketAddress) localAddress);
110 }
111
112 public boolean isReuseAddress() {
113 return reuseAddress;
114 }
115
116 public void setReuseAddress(boolean reuseAddress) {
117 synchronized (bindLock) {
118 if (isActive()) {
119 throw new IllegalStateException(
120 "reuseAddress can't be set while the acceptor is bound.");
121 }
122
123 this.reuseAddress = reuseAddress;
124 }
125 }
126
127 public int getBacklog() {
128 return backlog;
129 }
130
131 public void setBacklog(int backlog) {
132 synchronized (bindLock) {
133 if (isActive()) {
134 throw new IllegalStateException(
135 "backlog can't be set while the acceptor is bound.");
136 }
137
138 this.backlog = backlog;
139 }
140 }
141
142
143 @Override
144 protected NioSession accept(IoProcessor<NioSession> processor,
145 ServerSocketChannel handle) throws Exception {
146
147 SelectionKey key = handle.keyFor(selector);
148 if (!key.isAcceptable()) {
149 return null;
150 }
151
152
153 SocketChannel ch = handle.accept();
154 if (ch == null) {
155 return null;
156 }
157
158 return new NioSocketSession(this, processor, ch);
159 }
160
161 @Override
162 protected ServerSocketChannel open(SocketAddress localAddress)
163 throws Exception {
164 ServerSocketChannel c = ServerSocketChannel.open();
165 boolean success = false;
166 try {
167 c.configureBlocking(false);
168
169 c.socket().setReuseAddress(isReuseAddress());
170 c.socket().setReceiveBufferSize(
171 getSessionConfig().getReceiveBufferSize());
172
173 c.socket().bind(localAddress, getBacklog());
174 c.register(selector, SelectionKey.OP_ACCEPT);
175 success = true;
176 } finally {
177 if (!success) {
178 close(c);
179 }
180 }
181 return c;
182 }
183
184 @Override
185 protected SocketAddress localAddress(ServerSocketChannel handle)
186 throws Exception {
187 return handle.socket().getLocalSocketAddress();
188 }
189
190 @Override
191 protected boolean select() throws Exception {
192 return selector.select() > 0;
193 }
194
195 @Override
196 protected Iterator<ServerSocketChannel> selectedHandles() {
197 return new ServerSocketChannelIterator(selector.selectedKeys());
198 }
199
200 @Override
201 protected void close(ServerSocketChannel handle) throws Exception {
202 SelectionKey key = handle.keyFor(selector);
203 if (key != null) {
204 key.cancel();
205 }
206 handle.close();
207 }
208
209 @Override
210 protected void wakeup() {
211 selector.wakeup();
212 }
213
214 private static class ServerSocketChannelIterator implements Iterator<ServerSocketChannel> {
215
216 private final Iterator<SelectionKey> i;
217
218 private ServerSocketChannelIterator(Collection<SelectionKey> selectedKeys) {
219 this.i = selectedKeys.iterator();
220 }
221
222 public boolean hasNext() {
223 return i.hasNext();
224 }
225
226 public ServerSocketChannel next() {
227 SelectionKey key = i.next();
228 return (ServerSocketChannel) key.channel();
229 }
230
231 public void remove() {
232 i.remove();
233 }
234 }
235 }