1 package org.apache.commons.net;
2
3 /* ====================================================================
4 * The Apache Software License, Version 1.1
5 *
6 * Copyright (c) 2001 The Apache Software Foundation. All rights
7 * reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 *
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 *
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in
18 * the documentation and/or other materials provided with the
19 * distribution.
20 *
21 * 3. The end-user documentation included with the redistribution,
22 * if any, must include the following acknowledgment:
23 * "This product includes software developed by the
24 * Apache Software Foundation (http://www.apache.org/)."
25 * Alternately, this acknowledgment may appear in the software itself,
26 * if and wherever such third-party acknowledgments normally appear.
27 *
28 * 4. The names "Apache" and "Apache Software Foundation" and
29 * "Apache Commons" must not be used to endorse or promote products
30 * derived from this software without prior written permission. For
31 * written permission, please contact apache@apache.org.
32 *
33 * 5. Products derived from this software may not be called "Apache",
34 * nor may "Apache" appear in their name, without
35 * prior written permission of the Apache Software Foundation.
36 *
37 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
38 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
39 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
40 * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
41 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
42 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
43 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
44 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
45 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
46 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
47 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
48 * SUCH DAMAGE.
49 * ====================================================================
50 *
51 * This software consists of voluntary contributions made by many
52 * individuals on behalf of the Apache Software Foundation. For more
53 * information on the Apache Software Foundation, please see
54 * <http://www.apache.org/>.
55 */
56
57 import java.io.IOException;
58 import java.io.InputStream;
59 import java.io.OutputStream;
60 import java.net.InetAddress;
61 import java.net.Socket;
62 import java.net.SocketException;
63
64 /***
65 * The SocketClient provides the basic operations that are required of
66 * client objects accessing sockets. It is meant to be
67 * subclassed to avoid having to rewrite the same code over and over again
68 * to open a socket, close a socket, set timeouts, etc. Of special note
69 * is the <a href="#setSocketFactory"> setSocketFactory </a>
70 * method, which allows you to control the type of Socket the SocketClient
71 * creates for initiating network connections. This is especially useful
72 * for adding SSL or proxy support as well as better support for applets. For
73 * example, you could create a
74 * <a href="org.apache.commons.net.SocketFactory.html"> SocketFactory </a> that
75 * requests browser security capabilities before creating a socket.
76 * All classes derived from SocketClient should use the
77 * <a href="#_socketFactory_"> _socketFactory_ </a> member variable to
78 * create Socket and ServerSocket instances rather than instanting
79 * them by directly invoking a constructor. By honoring this contract
80 * you guarantee that a user will always be able to provide his own
81 * Socket implementations by substituting his own SocketFactory.
82 * @author Daniel F. Savarese
83 * @see SocketFactory
84 */
85 public abstract class SocketClient
86 {
87 /***
88 * The end of line character sequence used by most IETF protocols. That
89 * is a carriage return followed by a newline: "\r\n"
90 */
91 public static final String NETASCII_EOL = "\r\n";
92
93 /*** The default SocketFactory shared by all SocketClient instances. */
94 private static final SocketFactory __DEFAULT_SOCKET_FACTORY =
95 new DefaultSocketFactory();
96
97 /*** The timeout to use after opening a socket. */
98 protected int _timeout_;
99
100 /*** The socket used for the connection. */
101 protected Socket _socket_;
102
103 /***
104 * A status variable indicating if the client's socket is currently open.
105 */
106 protected boolean _isConnected_;
107
108 /*** The default port the client should connect to. */
109 protected int _defaultPort_;
110
111 /*** The socket's InputStream. */
112 protected InputStream _input_;
113
114 /*** The socket's OutputStream. */
115 protected OutputStream _output_;
116
117 /*** The socket's SocketFactory. */
118 protected SocketFactory _socketFactory_;
119
120
121 /***
122 * Default constructor for SocketClient. Initializes
123 * _socket_ to null, _timeout_ to 0, _defaultPort to 0,
124 * _isConnected_ to false, and _socketFactory_ to a shared instance of
125 * <a href="org.apache.commons.net.DefaultSocketFactory.html">DefaultSocketFactory </a>.
126 */
127 public SocketClient()
128 {
129 _socket_ = null;
130 _input_ = null;
131 _output_ = null;
132 _timeout_ = 0;
133 _defaultPort_ = 0;
134 _isConnected_ = false;
135 _socketFactory_ = __DEFAULT_SOCKET_FACTORY;
136 }
137
138
139 /***
140 * Because there are so many connect() methods, the _connectAction_()
141 * method is provided as a means of performing some action immediately
142 * after establishing a connection, rather than reimplementing all
143 * of the connect() methods. The last action performed by every
144 * connect() method after opening a socket is to call this method.
145 * <p>
146 * This method sets the timeout on the just opened socket to the default
147 * timeout set by <a href="#setDefaultTimeout"> setDefaultTimeout() </a>,
148 * sets _input_ and _output_ to the socket's InputStream and OutputStream
149 * respectively, and sets _isConnected_ to true.
150 * <p>
151 * Subclasses overriding this method should start by calling
152 * <code> super._connectAction_() </code> first to ensure the
153 * initialization of the aforementioned protected variables.
154 */
155 protected void _connectAction_() throws IOException
156 {
157 _socket_.setSoTimeout(_timeout_);
158 _input_ = _socket_.getInputStream();
159 _output_ = _socket_.getOutputStream();
160 _isConnected_ = true;
161 }
162
163
164 /***
165 * Opens a Socket connected to a remote host at the specified port and
166 * originating from the current host at a system assigned port.
167 * Before returning, <a href="#_connectAction_"> _connectAction_() </a>
168 * is called to perform connection initialization actions.
169 * <p>
170 * @param host The remote host.
171 * @param port The port to connect to on the remote host.
172 * @exception SocketException If the socket timeout could not be set.
173 * @exception IOException If the socket could not be opened. In most
174 * cases you will only want to catch IOException since SocketException is
175 * derived from it.
176 */
177 public void connect(InetAddress host, int port)
178 throws SocketException, IOException
179 {
180 _socket_ = _socketFactory_.createSocket(host, port);
181 _connectAction_();
182 }
183
184 /***
185 * Opens a Socket connected to a remote host at the specified port and
186 * originating from the current host at a system assigned port.
187 * Before returning, <a href="#_connectAction_"> _connectAction_() </a>
188 * is called to perform connection initialization actions.
189 * <p>
190 * @param hostname The name of the remote host.
191 * @param port The port to connect to on the remote host.
192 * @exception SocketException If the socket timeout could not be set.
193 * @exception IOException If the socket could not be opened. In most
194 * cases you will only want to catch IOException since SocketException is
195 * derived from it.
196 * @exception UnknownHostException If the hostname cannot be resolved.
197 */
198 public void connect(String hostname, int port)
199 throws SocketException, IOException
200 {
201 _socket_ = _socketFactory_.createSocket(hostname, port);
202 _connectAction_();
203 }
204
205
206 /***
207 * Opens a Socket connected to a remote host at the specified port and
208 * originating from the specified local address and port.
209 * Before returning, <a href="#_connectAction_"> _connectAction_() </a>
210 * is called to perform connection initialization actions.
211 * <p>
212 * @param host The remote host.
213 * @param port The port to connect to on the remote host.
214 * @param localAddr The local address to use.
215 * @param localPort The local port to use.
216 * @exception SocketException If the socket timeout could not be set.
217 * @exception IOException If the socket could not be opened. In most
218 * cases you will only want to catch IOException since SocketException is
219 * derived from it.
220 */
221 public void connect(InetAddress host, int port,
222 InetAddress localAddr, int localPort)
223 throws SocketException, IOException
224 {
225 _socket_ = _socketFactory_.createSocket(host, port, localAddr, localPort);
226 _connectAction_();
227 }
228
229
230 /***
231 * Opens a Socket connected to a remote host at the specified port and
232 * originating from the specified local address and port.
233 * Before returning, <a href="#_connectAction_"> _connectAction_() </a>
234 * is called to perform connection initialization actions.
235 * <p>
236 * @param hostname The name of the remote host.
237 * @param port The port to connect to on the remote host.
238 * @param localAddr The local address to use.
239 * @param localPort The local port to use.
240 * @exception SocketException If the socket timeout could not be set.
241 * @exception IOException If the socket could not be opened. In most
242 * cases you will only want to catch IOException since SocketException is
243 * derived from it.
244 * @exception UnknownHostException If the hostname cannot be resolved.
245 */
246 public void connect(String hostname, int port,
247 InetAddress localAddr, int localPort)
248 throws SocketException, IOException
249 {
250 _socket_ =
251 _socketFactory_.createSocket(hostname, port, localAddr, localPort);
252 _connectAction_();
253 }
254
255
256 /***
257 * Opens a Socket connected to a remote host at the current default port
258 * and originating from the current host at a system assigned port.
259 * Before returning, <a href="#_connectAction_"> _connectAction_() </a>
260 * is called to perform connection initialization actions.
261 * <p>
262 * @param host The remote host.
263 * @exception SocketException If the socket timeout could not be set.
264 * @exception IOException If the socket could not be opened. In most
265 * cases you will only want to catch IOException since SocketException is
266 * derived from it.
267 */
268 public void connect(InetAddress host) throws SocketException, IOException
269 {
270 connect(host, _defaultPort_);
271 }
272
273
274 /***
275 * Opens a Socket connected to a remote host at the current default
276 * port and originating from the current host at a system assigned port.
277 * Before returning, <a href="#_connectAction_"> _connectAction_() </a>
278 * is called to perform connection initialization actions.
279 * <p>
280 * @param hostname The name of the remote host.
281 * @exception SocketException If the socket timeout could not be set.
282 * @exception IOException If the socket could not be opened. In most
283 * cases you will only want to catch IOException since SocketException is
284 * derived from it.
285 * @exception UnknownHostException If the hostname cannot be resolved.
286 */
287 public void connect(String hostname) throws SocketException, IOException
288 {
289 connect(hostname, _defaultPort_);
290 }
291
292
293 /***
294 * Disconnects the socket connection.
295 * You should call this method after you've finished using the class
296 * instance and also before you call
297 * <a href="#connect">connect() </a>
298 * again. _isConnected_ is set to false, _socket_ is set to null,
299 * _input_ is set to null, and _output_ is set to null.
300 * <p>
301 * @exception IOException If there is an error closing the socket.
302 */
303 public void disconnect() throws IOException
304 {
305 _socket_.close();
306 _input_.close();
307 _output_.close();
308 _socket_ = null;
309 _input_ = null;
310 _output_ = null;
311 _isConnected_ = false;
312 }
313
314
315 /***
316 * Returns true if the client is currently connected to a server.
317 * <p>
318 * @return True if the client is currently connected to a server,
319 * false otherwise.
320 */
321 public boolean isConnected()
322 {
323 return _isConnected_;
324 }
325
326
327 /***
328 * Sets the default port the SocketClient should connect to when a port
329 * is not specified. The <a href="#_defaultPort_"> _defaultPort_ </a>
330 * variable stores this value. If never set, the default port is equal
331 * to zero.
332 * <p>
333 * @param port The default port to set.
334 */
335 public void setDefaultPort(int port)
336 {
337 _defaultPort_ = port;
338 }
339
340 /***
341 * Returns the current value of the default port (stored in
342 * <a href="#_defaultPort_"> _defaultPort_ </a>).
343 * <p>
344 * @return The current value of the default port.
345 */
346 public int getDefaultPort()
347 {
348 return _defaultPort_;
349 }
350
351
352 /***
353 * Set the default timeout in milliseconds to use when opening a socket.
354 * This value is only used previous to a call to
355 * <a href="#connect">connect()</a>
356 * and should not be confused with <a href="#setSoTimeout">setSoTimeout()</a>
357 * which operates on an the currently opened socket. _timeout_ contains
358 * the new timeout value.
359 * <p>
360 * @param timeout The timeout in milliseconds to use for the socket
361 * connection.
362 */
363 public void setDefaultTimeout(int timeout)
364 {
365 _timeout_ = timeout;
366 }
367
368
369 /***
370 * Returns the default timeout in milliseconds that is used when
371 * opening a socket.
372 * <p>
373 * @return The default timeout in milliseconds that is used when
374 * opening a socket.
375 */
376 public int getDefaultTimeout()
377 {
378 return _timeout_;
379 }
380
381
382 /***
383 * Set the timeout in milliseconds of a currently open connection.
384 * Only call this method after a connection has been opened
385 * by <a href="#connect">connect()</a>.
386 * <p>
387 * @param timeout The timeout in milliseconds to use for the currently
388 * open socket connection.
389 * @exception SocketException If the operation fails.
390 */
391 public void setSoTimeout(int timeout) throws SocketException
392 {
393 _socket_.setSoTimeout(timeout);
394 }
395
396
397 /***
398 * Returns the timeout in milliseconds of the currently opened socket.
399 * <p>
400 * @return The timeout in milliseconds of the currently opened socket.
401 * @exception SocketException If the operation fails.
402 */
403 public int getSoTimeout() throws SocketException
404 {
405 return _socket_.getSoTimeout();
406 }
407
408 /***
409 * Enables or disables the Nagle's algorithm (TCP_NODELAY) on the
410 * currently opened socket.
411 * <p>
412 * @param on True if Nagle's algorithm is to be enabled, false if not.
413 * @exception SocketException If the operation fails.
414 */
415 public void setTcpNoDelay(boolean on) throws SocketException
416 {
417 _socket_.setTcpNoDelay(on);
418 }
419
420
421 /***
422 * Returns true if Nagle's algorithm is enabled on the currently opened
423 * socket.
424 * <p>
425 * @return True if Nagle's algorithm is enabled on the currently opened
426 * socket, false otherwise.
427 * @exception SocketException If the operation fails.
428 */
429 public boolean getTcpNoDelay() throws SocketException
430 {
431 return _socket_.getTcpNoDelay();
432 }
433
434
435 /***
436 * Sets the SO_LINGER timeout on the currently opened socket.
437 * <p>
438 * @param on True if linger is to be enabled, false if not.
439 * @param val The linger timeout (in hundredths of a second?)
440 * @exception SocketException If the operation fails.
441 */
442 public void setSoLinger(boolean on, int val) throws SocketException
443 {
444 _socket_.setSoLinger(on, val);
445 }
446
447
448 /***
449 * Returns the current SO_LINGER timeout of the currently opened socket.
450 * <p>
451 * @return The current SO_LINGER timeout. If SO_LINGER is disabled returns
452 * -1.
453 * @exception SocketException If the operation fails.
454 */
455 public int getSoLinger() throws SocketException
456 {
457 return _socket_.getSoLinger();
458 }
459
460
461 /***
462 * Returns the port number of the open socket on the local host used
463 * for the connection.
464 * <p>
465 * @return The port number of the open socket on the local host used
466 * for the connection.
467 */
468 public int getLocalPort()
469 {
470 return _socket_.getLocalPort();
471 }
472
473
474 /***
475 * Returns the local address to which the client's socket is bound.
476 * <p>
477 * @return The local address to which the client's socket is bound.
478 */
479 public InetAddress getLocalAddress()
480 {
481 return _socket_.getLocalAddress();
482 }
483
484 /***
485 * Returns the port number of the remote host to which the client is
486 * connected.
487 * <p>
488 * @return The port number of the remote host to which the client is
489 * connected.
490 */
491 public int getRemotePort()
492 {
493 return _socket_.getPort();
494 }
495
496
497 /***
498 * @return The remote address to which the client is connected.
499 */
500 public InetAddress getRemoteAddress()
501 {
502 return _socket_.getInetAddress();
503 }
504
505
506 /***
507 * Verifies that the remote end of the given socket is connected to the
508 * the same host that the SocketClient is currently connected to. This
509 * is useful for doing a quick security check when a client needs to
510 * accept a connection from a server, such as an FTP data connection or
511 * a BSD R command standard error stream.
512 * <p>
513 * @return True if the remote hosts are the same, false if not.
514 */
515 public boolean verifyRemote(Socket socket)
516 {
517 InetAddress host1, host2;
518
519 host1 = socket.getInetAddress();
520 host2 = getRemoteAddress();
521
522 return host1.equals(host2);
523 }
524
525
526 /***
527 * Sets the SocketFactory used by the SocketClient to open socket
528 * connections. If the factory value is null, then a default
529 * factory is used (only do this to reset the factory after having
530 * previously altered it).
531 * <p>
532 * @param factory The new SocketFactory the SocketClient should use.
533 */
534 public void setSocketFactory(SocketFactory factory)
535 {
536 if (factory == null)
537 _socketFactory_ = __DEFAULT_SOCKET_FACTORY;
538 else
539 _socketFactory_ = factory;
540 }
541 }
542
543
This page was automatically generated by Maven