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.io.IOException;
23 import java.net.InetSocketAddress;
24 import java.net.SocketAddress;
25 import java.nio.channels.SelectionKey;
26 import java.nio.channels.Selector;
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.AbstractPollingIoConnector;
33 import org.apache.mina.core.service.IoConnector;
34 import org.apache.mina.core.service.IoProcessor;
35 import org.apache.mina.core.service.IoService;
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.SocketConnector;
40 import org.apache.mina.transport.socket.SocketSessionConfig;
41
42
43
44
45
46
47 public final class NioSocketConnector extends AbstractPollingIoConnector<NioSession, SocketChannel> implements
48 SocketConnector {
49
50 private volatile Selector selector;
51
52
53
54
55 public NioSocketConnector() {
56 super(new DefaultSocketSessionConfig(), NioProcessor.class);
57 ((DefaultSocketSessionConfig) getSessionConfig()).init(this);
58 }
59
60
61
62
63
64
65
66 public NioSocketConnector(int processorCount) {
67 super(new DefaultSocketSessionConfig(), NioProcessor.class, processorCount);
68 ((DefaultSocketSessionConfig) getSessionConfig()).init(this);
69 }
70
71
72
73
74
75
76
77 public NioSocketConnector(IoProcessor<NioSession> processor) {
78 super(new DefaultSocketSessionConfig(), processor);
79 ((DefaultSocketSessionConfig) getSessionConfig()).init(this);
80 }
81
82
83
84
85
86
87
88
89 public NioSocketConnector(Executor executor, IoProcessor<NioSession> processor) {
90 super(new DefaultSocketSessionConfig(), executor, processor);
91 ((DefaultSocketSessionConfig) getSessionConfig()).init(this);
92 }
93
94
95
96
97
98
99
100
101
102
103
104
105 public NioSocketConnector(Class<? extends IoProcessor<NioSession>> processorClass, int processorCount) {
106 super(new DefaultSocketSessionConfig(), processorClass, processorCount);
107 }
108
109
110
111
112
113
114
115
116
117
118
119
120
121 public NioSocketConnector(Class<? extends IoProcessor<NioSession>> processorClass) {
122 super(new DefaultSocketSessionConfig(), processorClass);
123 }
124
125
126
127
128 @Override
129 protected void init() throws Exception {
130 this.selector = Selector.open();
131 }
132
133
134
135
136 @Override
137 protected void destroy() throws Exception {
138 if (selector != null) {
139 selector.close();
140 }
141 }
142
143
144
145
146 public TransportMetadata getTransportMetadata() {
147 return NioSocketSession.METADATA;
148 }
149
150
151
152
153 public SocketSessionConfig getSessionConfig() {
154 return (SocketSessionConfig) sessionConfig;
155 }
156
157
158
159
160 @Override
161 public InetSocketAddress getDefaultRemoteAddress() {
162 return (InetSocketAddress) super.getDefaultRemoteAddress();
163 }
164
165
166
167
168 public void setDefaultRemoteAddress(InetSocketAddress defaultRemoteAddress) {
169 super.setDefaultRemoteAddress(defaultRemoteAddress);
170 }
171
172
173
174
175 @Override
176 protected Iterator<SocketChannel> allHandles() {
177 return new SocketChannelIterator(selector.keys());
178 }
179
180
181
182
183 @Override
184 protected boolean connect(SocketChannel handle, SocketAddress remoteAddress) throws Exception {
185 return handle.connect(remoteAddress);
186 }
187
188
189
190
191 @Override
192 protected ConnectionRequest getConnectionRequest(SocketChannel handle) {
193 SelectionKey key = handle.keyFor(selector);
194
195 if ((key == null) || (!key.isValid())) {
196 return null;
197 }
198
199 return (ConnectionRequest) key.attachment();
200 }
201
202
203
204
205 @Override
206 protected void close(SocketChannel handle) throws Exception {
207 SelectionKey key = handle.keyFor(selector);
208
209 if (key != null) {
210 key.cancel();
211 }
212
213 handle.close();
214 }
215
216
217
218
219 @Override
220 protected boolean finishConnect(SocketChannel handle) throws Exception {
221 if (handle.finishConnect()) {
222 SelectionKey key = handle.keyFor(selector);
223
224 if (key != null) {
225 key.cancel();
226 }
227
228 return true;
229 }
230
231 return false;
232 }
233
234
235
236
237 @Override
238 protected SocketChannel newHandle(SocketAddress localAddress) throws Exception {
239 SocketChannel ch = SocketChannel.open();
240
241 int receiveBufferSize = (getSessionConfig()).getReceiveBufferSize();
242
243 if (receiveBufferSize > 65535) {
244 ch.socket().setReceiveBufferSize(receiveBufferSize);
245 }
246
247 if (localAddress != null) {
248 try {
249 ch.socket().bind(localAddress);
250 } catch (IOException ioe) {
251
252
253 String newMessage = "Error while binding on " + localAddress + "\n" + "original message : "
254 + ioe.getMessage();
255 Exception e = new IOException(newMessage);
256 e.initCause(ioe.getCause());
257
258
259 ch.close();
260 throw ioe;
261 }
262 }
263
264 ch.configureBlocking(false);
265
266 return ch;
267 }
268
269
270
271
272 @Override
273 protected NioSession newSession(IoProcessor<NioSession> processor, SocketChannel handle) {
274 return new NioSocketSession(this, processor, handle);
275 }
276
277
278
279
280 @Override
281 protected void register(SocketChannel handle, ConnectionRequest request) throws Exception {
282 handle.register(selector, SelectionKey.OP_CONNECT, request);
283 }
284
285
286
287
288 @Override
289 protected int select(int timeout) throws Exception {
290 return selector.select(timeout);
291 }
292
293
294
295
296 @Override
297 protected Iterator<SocketChannel> selectedHandles() {
298 return new SocketChannelIterator(selector.selectedKeys());
299 }
300
301
302
303
304 @Override
305 protected void wakeup() {
306 selector.wakeup();
307 }
308
309 private static class SocketChannelIterator implements Iterator<SocketChannel> {
310
311 private final Iterator<SelectionKey> i;
312
313 private SocketChannelIterator(Collection<SelectionKey> selectedKeys) {
314 this.i = selectedKeys.iterator();
315 }
316
317
318
319
320 public boolean hasNext() {
321 return i.hasNext();
322 }
323
324
325
326
327 public SocketChannel next() {
328 SelectionKey key = i.next();
329 return (SocketChannel) key.channel();
330 }
331
332
333
334
335 public void remove() {
336 i.remove();
337 }
338 }
339 }