| /*** |
| * $Id: SocketClient.java,v 1.1 2002/04/03 01:04:26 brekke Exp $ |
| * |
| * NetComponents Internet Protocol Library |
| * Copyright (C) 1997-2002 Daniel F. Savarese |
| * |
| * This library is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU Lesser General Public |
| * License as published by the Free Software Foundation; either |
| * version 2.1 of the License, or (at your option) any later version. |
| * |
| * This library is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| * Lesser General Public License for more details. |
| * |
| * You should have received a copy of the GNU Lesser General Public |
| * License along with this library in the LICENSE file; if not, write |
| * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, |
| * Boston, MA 02111-1307 USA |
| ***/ |
| |
| package com.oroinc.net; |
| |
| import java.io.*; |
| import java.net.*; |
| |
| /*** |
| * The SocketClient provides the basic operations that are required |
| * of client objects accessing sockets. It is meant to be |
| * subclassed to avoid having to rewrite the same code over and over again |
| * to open a socket, close a socket, set timeouts, etc. Of special note |
| * is the <a href="#setSocketFactory"> setSocketFactory </a> |
| * method, which |
| * allows you to control the type of Socket the SocketClient creates for |
| * initiating network connections. This is especially useful for adding |
| * SSL or proxy support as well as better support for applets. For |
| * example, you could create a |
| * <a href="com.oroinc.net.SocketFactory.html"> SocketFactory </a> that |
| * requests browser security capabilities before creating a socket. |
| * All classes derived from SocketClient should use the |
| * <a href="#_socketFactory_"> _socketFactory_ </a> member variable to |
| * create Socket and ServerSocket instances rather than instanting |
| * them by directly invoking a constructor. By honoring this contract |
| * you guarantee that a user will always be able to provide his own |
| * Socket implementations by substituting his own SocketFactory. |
| * <p> |
| * <p> |
| * @author Daniel F. Savarese |
| * @see SocketFactory |
| ***/ |
| |
| public abstract class SocketClient { |
| /*** |
| * The end of line character sequence used by most IETF protocols. That |
| * is a carriage return followed by a newline: "\r\n" |
| ***/ |
| public static final String NETASCII_EOL = "\r\n"; |
| |
| /*** The default SocketFactory shared by all SocketClient instances. ***/ |
| private static final SocketFactory __DEFAULT_SOCKET_FACTORY = |
| new DefaultSocketFactory(); |
| |
| /*** The timeout to use after opening a socket. ***/ |
| protected int _timeout_; |
| |
| /*** The socket used for the connection. ***/ |
| protected Socket _socket_; |
| |
| /*** |
| * A status variable indicating if the client's socket is currently open. |
| ***/ |
| protected boolean _isConnected_; |
| |
| /*** The default port the client should connect to. ***/ |
| protected int _defaultPort_; |
| |
| /*** The socket's InputStream. ***/ |
| protected InputStream _input_; |
| |
| /*** The socket's OutputStream. ***/ |
| protected OutputStream _output_; |
| |
| /*** The socket's SocketFactory. ***/ |
| protected SocketFactory _socketFactory_; |
| |
| |
| /*** |
| * Default constructor for SocketClient. Initializes |
| * _socket_ to null, _timeout_ to 0, _defaultPort to 0, |
| * _isConnected_ to false, and _socketFactory_ to a shared instance of |
| * <a href="com.oroinc.net.DefaultSocketFactory.html"> |
| * DefaultSocketFactory </a>. |
| ***/ |
| public SocketClient() { |
| _socket_ = null; |
| _input_ = null; |
| _output_ = null; |
| _timeout_ = 0; |
| _defaultPort_ = 0; |
| _isConnected_ = false; |
| _socketFactory_ = __DEFAULT_SOCKET_FACTORY; |
| } |
| |
| |
| /*** |
| * Because there are so many connect() methods, the _connectAction_() |
| * method is provided as a means of performing some action immediately |
| * after establishing a connection, rather than reimplementing all |
| * of the connect() methods. The last action performed by every |
| * connect() method after opening a socket is to call this method. |
| * <p> |
| * This method sets the timeout on the just opened socket to the default |
| * timeout set by <a href="#setDefaultTimeout"> setDefaultTimeout() </a>, |
| * sets _input_ and _output_ to the socket's InputStream and OutputStream |
| * respectively, and sets _isConnected_ to true. |
| * <p> |
| * Subclasses overriding this method should start by calling |
| * <code> super._connectAction_() </code> first to ensure the |
| * initialization of the aforementioned protected variables. |
| ***/ |
| protected void _connectAction_() throws IOException { |
| _socket_.setSoTimeout(_timeout_); |
| _input_ = _socket_.getInputStream(); |
| _output_ = _socket_.getOutputStream(); |
| _isConnected_ = true; |
| } |
| |
| |
| /*** |
| * Opens a Socket connected to a remote host at the specified port and |
| * originating from the current host at a system assigned port. |
| * Before returning, <a href="#_connectAction_"> _connectAction_() </a> |
| * is called to perform connection initialization actions. |
| * <p> |
| * @param host The remote host. |
| * @param port The port to connect to on the remote host. |
| * @exception SocketException If the socket timeout could not be set. |
| * @exception IOException If the socket could not be opened. In most |
| * cases you will only want to catch IOException since SocketException is |
| * derived from it. |
| ***/ |
| public void connect(InetAddress host, int port) |
| throws SocketException, IOException |
| { |
| _socket_ = _socketFactory_.createSocket(host, port); |
| _connectAction_(); |
| } |
| |
| /*** |
| * Opens a Socket connected to a remote host at the specified port and |
| * originating from the current host at a system assigned port. |
| * Before returning, <a href="#_connectAction_"> _connectAction_() </a> |
| * is called to perform connection initialization actions. |
| * <p> |
| * @param hostname The name of the remote host. |
| * @param port The port to connect to on the remote host. |
| * @exception SocketException If the socket timeout could not be set. |
| * @exception IOException If the socket could not be opened. In most |
| * cases you will only want to catch IOException since SocketException is |
| * derived from it. |
| * @exception UnknownHostException If the hostname cannot be resolved. |
| ***/ |
| public void connect(String hostname, int port) |
| throws SocketException, IOException |
| { |
| _socket_ = _socketFactory_.createSocket(hostname, port); |
| _connectAction_(); |
| } |
| |
| |
| /*** |
| * Opens a Socket connected to a remote host at the specified port and |
| * originating from the specified local address and port. |
| * Before returning, <a href="#_connectAction_"> _connectAction_() </a> |
| * is called to perform connection initialization actions. |
| * <p> |
| * @param host The remote host. |
| * @param port The port to connect to on the remote host. |
| * @param localAddr The local address to use. |
| * @param localPort The local port to use. |
| * @exception SocketException If the socket timeout could not be set. |
| * @exception IOException If the socket could not be opened. In most |
| * cases you will only want to catch IOException since SocketException is |
| * derived from it. |
| ***/ |
| public void connect(InetAddress host, int port, |
| InetAddress localAddr, int localPort) |
| throws SocketException, IOException |
| { |
| _socket_ = _socketFactory_.createSocket(host, port, localAddr, localPort); |
| _connectAction_(); |
| } |
| |
| |
| /*** |
| * Opens a Socket connected to a remote host at the specified port and |
| * originating from the specified local address and port. |
| * Before returning, <a href="#_connectAction_"> _connectAction_() </a> |
| * is called to perform connection initialization actions. |
| * <p> |
| * @param hostname The name of the remote host. |
| * @param port The port to connect to on the remote host. |
| * @param localAddr The local address to use. |
| * @param localPort The local port to use. |
| * @exception SocketException If the socket timeout could not be set. |
| * @exception IOException If the socket could not be opened. In most |
| * cases you will only want to catch IOException since SocketException is |
| * derived from it. |
| * @exception UnknownHostException If the hostname cannot be resolved. |
| ***/ |
| public void connect(String hostname, int port, |
| InetAddress localAddr, int localPort) |
| throws SocketException, IOException |
| { |
| _socket_ = |
| _socketFactory_.createSocket(hostname, port, localAddr, localPort); |
| _connectAction_(); |
| } |
| |
| |
| /*** |
| * Opens a Socket connected to a remote host at the current default port |
| * and originating from the current host at a system assigned port. |
| * Before returning, <a href="#_connectAction_"> _connectAction_() </a> |
| * is called to perform connection initialization actions. |
| * <p> |
| * @param host The remote host. |
| * @exception SocketException If the socket timeout could not be set. |
| * @exception IOException If the socket could not be opened. In most |
| * cases you will only want to catch IOException since SocketException is |
| * derived from it. |
| ***/ |
| public void connect(InetAddress host) throws SocketException, IOException { |
| connect(host, _defaultPort_); |
| } |
| |
| |
| /*** |
| * Opens a Socket connected to a remote host at the current default |
| * port and originating from the current host at a system assigned port. |
| * Before returning, <a href="#_connectAction_"> _connectAction_() </a> |
| * is called to perform connection initialization actions. |
| * <p> |
| * @param hostname The name of the remote host. |
| * @exception SocketException If the socket timeout could not be set. |
| * @exception IOException If the socket could not be opened. In most |
| * cases you will only want to catch IOException since SocketException is |
| * derived from it. |
| * @exception UnknownHostException If the hostname cannot be resolved. |
| ***/ |
| public void connect(String hostname) throws SocketException, IOException { |
| connect(hostname, _defaultPort_); |
| } |
| |
| |
| /*** |
| * Disconnects the socket connection. |
| * You should call this method after you've finished using the class |
| * instance and also before you call |
| * <a href="#connect">connect() </a> |
| * again. _isConnected_ is set to false, _socket_ is set to null, |
| * _input_ is set to null, and _output_ is set to null. |
| * <p> |
| * @exception IOException If there is an error closing the socket. |
| ***/ |
| public void disconnect() throws IOException { |
| _socket_.close(); |
| _input_.close(); |
| _output_.close(); |
| _socket_ = null; |
| _input_ = null; |
| _output_ = null; |
| _isConnected_ = false; |
| } |
| |
| |
| /*** |
| * Returns true if the client is currently connected to a server. |
| * <p> |
| * @return True if the client is currently connected to a server, |
| * false otherwise. |
| ***/ |
| public boolean isConnected() { |
| return _isConnected_; |
| } |
| |
| |
| /*** |
| * Sets the default port the SocketClient should connect to when a port |
| * is not specified. The <a href="#_defaultPort_"> _defaultPort_ </a> |
| * variable stores this value. If never set, the default port is equal |
| * to zero. |
| * <p> |
| * @param port The default port to set. |
| ***/ |
| public void setDefaultPort(int port) { _defaultPort_ = port; } |
| |
| /*** |
| * Returns the current value of the default port (stored in |
| * <a href="#_defaultPort_"> _defaultPort_ </a>). |
| * <p> |
| * @return The current value of the default port. |
| ***/ |
| public int getDefaultPort() { return _defaultPort_; } |
| |
| |
| /*** |
| * Set the default timeout in milliseconds to use when opening a socket. |
| * This value is only used previous to a call to |
| * <a href="#connect">connect()</a> |
| * and should not be confused with <a href="#setSoTimeout">setSoTimeout()</a> |
| * which operates on an the currently opened socket. _timeout_ contains |
| * the new timeout value. |
| * <p> |
| * @param timeout The timeout in milliseconds to use for the socket |
| * connection. |
| ***/ |
| public void setDefaultTimeout(int timeout) { _timeout_ = timeout; } |
| |
| |
| /*** |
| * Returns the default timeout in milliseconds that is used when |
| * opening a socket. |
| * <p> |
| * @return The default timeout in milliseconds that is used when |
| * opening a socket. |
| ***/ |
| public int getDefaultTimeout() { return _timeout_; } |
| |
| |
| /*** |
| * Set the timeout in milliseconds of a currently open connection. |
| * Only call this method after a connection has been opened |
| * by <a href="#connect">connect()</a>. |
| * <p> |
| * @param timeout The timeout in milliseconds to use for the currently |
| * open socket connection. |
| * @exception SocketException If the operation fails. |
| ***/ |
| public void setSoTimeout(int timeout) throws SocketException { |
| _socket_.setSoTimeout(timeout); |
| } |
| |
| |
| /*** |
| * Returns the timeout in milliseconds of the currently opened socket. |
| * <p> |
| * @return The timeout in milliseconds of the currently opened socket. |
| * @exception SocketException If the operation fails. |
| ***/ |
| public int getSoTimeout() throws SocketException { |
| return _socket_.getSoTimeout(); |
| } |
| |
| /*** |
| * Enables or disables the Nagle's algorithm (TCP_NODELAY) on the |
| * currently opened socket. |
| * <p> |
| * @param on True if Nagle's algorithm is to be enabled, false if not. |
| * @exception SocketException If the operation fails. |
| ***/ |
| public void setTcpNoDelay(boolean on) throws SocketException { |
| _socket_.setTcpNoDelay(on); |
| } |
| |
| |
| /*** |
| * Returns true if Nagle's algorithm is enabled on the currently opened |
| * socket. |
| * <p> |
| * @return True if Nagle's algorithm is enabled on the currently opened |
| * socket, false otherwise. |
| * @exception SocketException If the operation fails. |
| ***/ |
| public boolean getTcpNoDelay() throws SocketException { |
| return _socket_.getTcpNoDelay(); |
| } |
| |
| |
| /*** |
| * Sets the SO_LINGER timeout on the currently opened socket. |
| * <p> |
| * @param on True if linger is to be enabled, false if not. |
| * @param val The linger timeout (in hundredths of a second?) |
| * @exception SocketException If the operation fails. |
| ***/ |
| public void setSoLinger(boolean on, int val) throws SocketException { |
| _socket_.setSoLinger(on, val); |
| } |
| |
| |
| /*** |
| * Returns the current SO_LINGER timeout of the currently opened socket. |
| * <p> |
| * @return The current SO_LINGER timeout. If SO_LINGER is disabled returns |
| * -1. |
| * @exception SocketException If the operation fails. |
| ***/ |
| public int getSoLinger() throws SocketException { |
| return _socket_.getSoLinger(); |
| } |
| |
| |
| /*** |
| * Returns the port number of the open socket on the local host used |
| * for the connection. |
| * <p> |
| * @return The port number of the open socket on the local host used |
| * for the connection. |
| ***/ |
| public int getLocalPort() { return _socket_.getLocalPort(); } |
| |
| |
| /*** |
| * Returns the local address to which the client's socket is bound. |
| * <p> |
| * @return The local address to which the client's socket is bound. |
| ***/ |
| public InetAddress getLocalAddress() { |
| return _socket_.getLocalAddress(); |
| } |
| |
| /*** |
| * Returns the port number of the remote host to which the client is |
| * connected. |
| * <p> |
| * @return The port number of the remote host to which the client is |
| * connected. |
| ***/ |
| public int getRemotePort() { return _socket_.getPort(); } |
| |
| |
| /*** |
| * @return The remote address to which the client is connected. |
| ***/ |
| public InetAddress getRemoteAddress() { |
| return _socket_.getInetAddress(); |
| } |
| |
| |
| /*** |
| * Verifies that the remote end of the given socket is connected to the |
| * the same host that the SocketClient is currently connected to. This |
| * is useful for doing a quick security check when a client needs to |
| * accept a connection from a server, such as an FTP data connection or |
| * a BSD R command standard error stream. |
| * <p> |
| * @return True if the remote hosts are the same, false if not. |
| ***/ |
| public boolean verifyRemote(Socket socket) { |
| InetAddress host1, host2; |
| |
| host1 = socket.getInetAddress(); |
| host2 = getRemoteAddress(); |
| |
| return host1.equals(host2); |
| } |
| |
| |
| /*** |
| * Sets the SocketFactory used by the SocketClient to open socket |
| * connections. If the factory value is null, then a default |
| * factory is used (only do this to reset the factory after having |
| * previously altered it). |
| * <p> |
| * @param factory The new SocketFactory the SocketClient should use. |
| ***/ |
| public void setSocketFactory(SocketFactory factory) { |
| if(factory == null) |
| _socketFactory_ = __DEFAULT_SOCKET_FACTORY; |
| else |
| _socketFactory_ = factory; |
| } |
| } |
| |
| |