InetAddress.java (ANY_IF): moved from ServerSocket.

* java/net/InetAddress.java (ANY_IF): moved from ServerSocket.
        * java/net/DatagramSocket.java (DatagramSocket): use ANY_IF from
        InetAddress.
        * java/net/MulticastSocket.java (MulticastSocket): Likewise.
        * java/net/Socket.java: Merge with Classpath.
        * java/net/ServerSocket.java: Likewise.

From-SVN: r48797
This commit is contained in:
Mark Wielaard 2002-01-12 10:11:13 +00:00 committed by Mark Wielaard
parent e37af218ee
commit 9566a90c6b
6 changed files with 713 additions and 150 deletions

View file

@ -1,3 +1,12 @@
2002-01-11 Mark Wielaard <mark@klomp.org>
* java/net/InetAddress.java (ANY_IF): moved from ServerSocket.
* java/net/DatagramSocket.java (DatagramSocket): use ANY_IF from
InetAddress.
* java/net/MulticastSocket.java (MulticastSocket): Likewise.
* java/net/Socket.java: Merge with Classpath.
* java/net/ServerSocket.java: Likewise.
2002-01-11 Chris Sears <cbsears_sf@yahoo.com> 2002-01-11 Chris Sears <cbsears_sf@yahoo.com>
* interpret.cc (NULLARRAYCHECK): New macro. * interpret.cc (NULLARRAYCHECK): New macro.

View file

@ -28,12 +28,12 @@ public class DatagramSocket
public DatagramSocket() throws SocketException public DatagramSocket() throws SocketException
{ {
this(0, ServerSocket.ANY_IF); this(0, null);
} }
public DatagramSocket(int port) throws SocketException public DatagramSocket(int port) throws SocketException
{ {
this(port, ServerSocket.ANY_IF); this(port, null);
} }
public DatagramSocket(int port, InetAddress laddr) throws SocketException public DatagramSocket(int port, InetAddress laddr) throws SocketException
@ -66,7 +66,7 @@ public class DatagramSocket
if (this instanceof MulticastSocket) if (this instanceof MulticastSocket)
impl.setOption(SocketOptions.SO_REUSEADDR, new Boolean(true)); impl.setOption(SocketOptions.SO_REUSEADDR, new Boolean(true));
impl.bind(port, laddr == null ? ServerSocket.ANY_IF : laddr); impl.bind(port, laddr == null ? InetAddress.ANY_IF : laddr);
} }
public void close() public void close()

View file

@ -240,6 +240,10 @@ public final class InetAddress implements java.io.Serializable
return lookup(host, null, true); return lookup(host, null, true);
} }
static final byte[] zeros = {0,0,0,0};
/* dummy InetAddress, used to bind socket to any (all) network interfaces */
static final InetAddress ANY_IF = new InetAddress(zeros, null);
private static final byte[] localhostAddress = { 127, 0, 0, 1 }; private static final byte[] localhostAddress = { 127, 0, 0, 1 };
private static native String getLocalHostname (); private static native String getLocalHostname ();

View file

@ -64,7 +64,7 @@ public class MulticastSocket extends DatagramSocket
*/ */
public MulticastSocket() throws IOException public MulticastSocket() throws IOException
{ {
super(0, ServerSocket.ANY_IF); super(0, null);
} }
/** /**
@ -76,7 +76,7 @@ public class MulticastSocket extends DatagramSocket
*/ */
public MulticastSocket(int port) throws IOException public MulticastSocket(int port) throws IOException
{ {
super(port, ServerSocket.ANY_IF); super(port, null);
} }
/** /**

View file

@ -1,111 +1,265 @@
// ServerSocket.java /* ServerSocket.java -- Class for implementing server side sockets
Copyright (C) 1998, 1999, 2000, 2002 Free Software Foundation, Inc.
/* Copyright (C) 1999 Free Software Foundation This file is part of GNU Classpath.
This file is part of libgcj. GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath 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
General Public License for more details.
This software is copyrighted work licensed under the terms of the You should have received a copy of the GNU General Public License
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for along with GNU Classpath; see the file COPYING. If not, write to the
details. */ Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA.
/** As a special exception, if you link this library with other files to
* @author Per Bothner <bothner@cygnus.com> produce an executable, this library does not by itself cause the
* @date January 6, 1999. resulting executable to be covered by the GNU General Public License.
*/ This exception does not however invalidate any other reasons why the
executable file might be covered by the GNU General Public License. */
/** Written using on-line Java Platform 1.2 API Specification.
* Status: I believe all methods are implemented.
*/
package java.net; package java.net;
import java.io.*;
import java.io.IOException;
/* Written using on-line Java Platform 1.2 API Specification.
* Status: I believe all methods are implemented.
*/
/**
* This class models server side sockets. The basic model is that the
* server socket is created and bound to some well known port. It then
* listens for and accepts connections. At that point the client and
* server sockets are ready to communicate with one another utilizing
* whatever application layer protocol they desire.
* <p>
* As with the <code>Socket</code> class, most instance methods of this class
* simply redirect their calls to an implementation class.
*
* @author Aaron M. Renn (arenn@urbanophile.com)
* @author Per Bothner (bothner@cygnus.com)
*/
public class ServerSocket public class ServerSocket
{ {
static SocketImplFactory factory;
SocketImpl impl;
static final byte[] zeros = {0,0,0,0}; // Class Variables
/* dummy InetAddress, used to bind socket to any (all) network interfaces */
static final InetAddress ANY_IF = new InetAddress(zeros, null);
/**
* This is the user defined SocketImplFactory, if one is supplied
*/
private static SocketImplFactory factory;
// Instance Variables
/**
* This is the SocketImp object to which most instance methods in this
* class are redirected
*/
private SocketImpl impl;
/**
* Private constructor that simply sets the implementation.
*/
private ServerSocket()
{
if (factory != null)
impl = factory.createSocketImpl();
else
impl = new PlainSocketImpl();
}
/**
* Creates a server socket and binds it to the specified port. If the
* port number is 0, a random free port will be chosen. The pending
* connection queue on this socket will be set to 50.
*
* @param port The port number to bind to
*
* @exception IOException If an error occurs
*/
public ServerSocket (int port) public ServerSocket (int port)
throws java.io.IOException throws java.io.IOException
{ {
this(port, 50); this(port, 50);
} }
/**
* Creates a server socket and binds it to the specified port. If the
* port number is 0, a random free port will be chosen. The pending
* connection queue on this socket will be set to the value passed as
* arg2.
*
* @param port The port number to bind to
* @param backlog The length of the pending connection queue
*
* @exception IOException If an error occurs
*/
public ServerSocket (int port, int backlog) public ServerSocket (int port, int backlog)
throws java.io.IOException throws java.io.IOException
{ {
this(port, backlog, ANY_IF); this(port, backlog, null);
} }
/**
* Creates a server socket and binds it to the specified port. If the
* port number is 0, a random free port will be chosen. The pending
* connection queue on this socket will be set to the value passed as
* backlog. The third argument specifies a particular local address to
* bind t or null to bind to all local address.
*
* @param port The port number to bind to
* @param backlog The length of the pending connection queue
* @param bindAddr The address to bind to, or null to bind to all addresses
*
* @exception IOException If an error occurs
*/
public ServerSocket (int port, int backlog, InetAddress bindAddr) public ServerSocket (int port, int backlog, InetAddress bindAddr)
throws java.io.IOException throws java.io.IOException
{ {
if (factory == null) this();
this.impl = new PlainSocketImpl(); if (impl == null)
else throw new IOException("Cannot initialize Socket implementation");
this.impl = factory.createSocketImpl();
SecurityManager s = System.getSecurityManager(); SecurityManager s = System.getSecurityManager();
if (s != null) if (s != null)
s.checkListen(port); s.checkListen(port);
if (bindAddr == null)
bindAddr = InetAddress.ANY_IF;
impl.create(true); impl.create(true);
impl.bind(bindAddr == null ? ANY_IF : bindAddr, port); impl.bind(bindAddr, port);
impl.listen(backlog); impl.listen(backlog);
} }
/**
* This method returns the local address to which this socket is bound
*
* @return The socket's local address
*/
public InetAddress getInetAddress() public InetAddress getInetAddress()
{ {
return impl.getInetAddress(); return impl.getInetAddress();
} }
/**
* This method returns the local port number to which this socket is bound
*
* @return The socket's port number
*/
public int getLocalPort() public int getLocalPort()
{ {
return impl.getLocalPort(); return impl.getLocalPort();
} }
/**
* Accepts a new connection and returns a connected <code>Socket</code>
* instance representing that connection. This method will block until a
* connection is available.
*
* @exception IOException If an error occurs
*/
public Socket accept () throws IOException public Socket accept () throws IOException
{ {
Socket s = new Socket(Socket.factory == null ? new PlainSocketImpl() Socket s = new Socket();
: Socket.factory.createSocketImpl());
implAccept (s); implAccept (s);
return s; return s;
} }
/**
* This protected method is used to help subclasses override
* <code>ServerSocket.accept()</code>. The passed in socket will be
* connected when this method returns.
*
* @param socket The socket that is used for the accepted connection
*
* @exception IOException If an error occurs
*/
protected final void implAccept (Socket s) throws IOException protected final void implAccept (Socket s) throws IOException
{ {
impl.accept(s.impl); impl.accept(s.impl);
} }
/**
* Closes this socket and stops listening for connections
*
* @exception IOException If an error occurs
*/
public void close () throws IOException public void close () throws IOException
{ {
impl.close(); impl.close();
} }
public synchronized void setSoTimeout (int timeout) throws SocketException /**
* Sets the value of SO_TIMEOUT. A value of 0 implies that SO_TIMEOUT is
* disabled (ie, operations never time out). This is the number of
* milliseconds a socket operation can block before an
* InterruptedIOException is thrown.
*
* @param timeout The new SO_TIMEOUT value
*
* @exception IOException If an error occurs
*/
public void setSoTimeout (int timeout) throws SocketException
{ {
if (timeout < 0) if (timeout < 0)
throw new IllegalArgumentException("Invalid timeout: " + timeout); throw new IllegalArgumentException("SO_TIMEOUT value must be >= 0");
impl.setOption(SocketOptions.SO_TIMEOUT, new Integer(timeout)); impl.setOption(SocketOptions.SO_TIMEOUT, new Integer(timeout));
} }
public synchronized int getSoTimeout () throws SocketException /**
* Retrieves the current value of the SO_TIMEOUT setting. A value of 0
* implies that SO_TIMEOUT is disabled (ie, operations never time out).
* This is the number of milliseconds a socket operation can block before
* an InterruptedIOException is thrown.
*
* @return The value of SO_TIMEOUT
*
* @exception IOException If an error occurs
*/
public int getSoTimeout () throws IOException
{ {
Object timeout = impl.getOption(SocketOptions.SO_TIMEOUT); Object timeout = impl.getOption(SocketOptions.SO_TIMEOUT);
if (timeout instanceof Integer)
return ((Integer)timeout).intValue(); if (!(timeout instanceof Integer))
else throw new IOException("Internal Error");
return 0;
return ((Integer)timeout).intValue();
} }
/**
* Returns the value of this socket as a <code>String</code>.
*
* @return This socket represented as a <code>String</code>.
*/
public String toString () public String toString ()
{ {
return "ServerSocket" + impl.toString(); return "ServerSocket " + impl.toString();
} }
// Class methods
/**
* Sets the <code>SocketImplFactory</code> for all
* <code>ServerSocket</code>'s. This may only be done
* once per virtual machine. Subsequent attempts will generate an
* exception. Note that a <code>SecurityManager</code> check is made prior
* to setting the factory. If insufficient privileges exist to set the
* factory, an exception will be thrown
*
* @exception SecurityException If this operation is not allowed by the
* <code>SecurityManager</code>.
* @exception SocketException If the factory object is already defined
* @exception IOException If any other error occurs
*/
public static synchronized void setSocketFactory (SocketImplFactory fac) public static synchronized void setSocketFactory (SocketImplFactory fac)
throws IOException throws IOException
{ {

View file

@ -1,263 +1,659 @@
// Socket.java /* Socket.java -- Client socket implementation
Copyright (C) 1998, 1999, 2000, 2002 Free Software Foundation, Inc.
/* Copyright (C) 1999 Free Software Foundation This file is part of GNU Classpath.
This file is part of libgcj. GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath 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
General Public License for more details.
This software is copyrighted work licensed under the terms of the You should have received a copy of the GNU General Public License
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for along with GNU Classpath; see the file COPYING. If not, write to the
details. */ Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA.
/** As a special exception, if you link this library with other files to
* @author Per Bothner <bothner@cygnus.com> produce an executable, this library does not by itself cause the
* @date January 6, 1999. resulting executable to be covered by the GNU General Public License.
*/ This exception does not however invalidate any other reasons why the
executable file might be covered by the GNU General Public License. */
/** Written using on-line Java Platform 1.2 API Specification.
* Status: I believe all methods are implemented.
*/
package java.net; package java.net;
import java.io.*; import java.io.*;
/* Written using on-line Java Platform 1.2 API Specification.
* Status: I believe all methods are implemented.
*/
/**
* This class models a client site socket. A socket is a TCP/IP endpoint
* for network communications conceptually similar to a file handle.
* <p>
* This class does not actually do any work. Instead, it redirects all of
* its calls to a socket implementation object which implements the
* <code>SocketImpl</code> interface. The implementation class is
* instantiated by factory class that implements the
* <code>SocketImplFactory interface</code>. A default
* factory is provided, however the factory may be set by a call to
* the <code>setSocketImplFactory</code> method. Note that this may only be
* done once per virtual machine. If a subsequent attempt is made to set the
* factory, a <code>SocketException</code> will be thrown.
*
* @author Aaron M. Renn (arenn@urbanophile.com)
* @author Per Bothner (bothner@cygnus.com)
*/
public class Socket public class Socket
{ {
// Class Variables
/**
* This is the user SocketImplFactory for this class. If this variable is
* null, a default factory is used.
*/
static SocketImplFactory factory; static SocketImplFactory factory;
// Instance Variables
/**
* The implementation object to which calls are redirected
*/
SocketImpl impl; SocketImpl impl;
// Constructors
/**
* Initializes a new instance of <code>Socket</code> object without
* connecting to a remote host. This useful for subclasses of socket that
* might want this behavior.
*/
protected Socket () protected Socket ()
{ {
if (factory != null)
impl = factory.createSocketImpl();
else
impl = new PlainSocketImpl();
} }
/**
* Initializes a new instance of <code>Socket</code> object without
* connecting to a remote host. This is useful for subclasses of socket
* that might want this behavior.
* <p>
* Additionally, this socket will be created using the supplied
* implementation class instead the default class or one returned by a
* factory. This value can be <code>null</code>, but if it is, all instance
* methods in <code>Socket</code> should be overridden because most of them
* rely on this value being populated.
*
* @param impl The <code>SocketImpl</code> to use for this
* <code>Socket</code>
*
* @exception SocketException If an error occurs
*/
protected Socket (SocketImpl impl) throws SocketException protected Socket (SocketImpl impl) throws SocketException
{ {
this.impl = impl; this.impl = impl;
} }
/**
* Initializes a new instance of <code>Socket</code> and connects to the
* hostname and port specified as arguments.
*
* @param host The name of the host to connect to
* @param port The port number to connect to
*
* @exception UnknownHostException If the hostname cannot be resolved to a
* network address.
* @exception IOException If an error occurs
*/
public Socket (String host, int port) public Socket (String host, int port)
throws UnknownHostException, IOException throws UnknownHostException, IOException
{ {
this(factory == null ? new PlainSocketImpl() : factory.createSocketImpl()); this(InetAddress.getByName(host), port, null, 0, true);
SecurityManager s = System.getSecurityManager();
if (s != null)
s.checkConnect(host, port);
impl.create(true);
// FIXME: JCL p. 1586 says if localPort is unspecified, bind to any port,
// i.e. '0' and if localAddr is unspecified, use getLocalAddress() as
// that default. JDK 1.2 doc infers not to do a bind.
impl.connect(host, port);
} }
/**
* Initializes a new instance of <code>Socket</code> and connects to the
* address and port number specified as arguments.
*
* @param address The address to connect to
* @param port The port number to connect to
*
* @exception IOException If an error occurs
*/
public Socket (InetAddress address, int port) public Socket (InetAddress address, int port)
throws IOException throws IOException
{ {
this(factory == null ? new PlainSocketImpl() : factory.createSocketImpl()); this(address, port, null, 0, true);
SecurityManager s = System.getSecurityManager();
if (s != null)
s.checkConnect(address.getHostName(), port);
impl.create(true);
// FIXME: JCL p. 1586 says if localPort is unspecified, bind to any port,
// i.e. '0' and if localAddr is unspecified, use getLocalAddress() as
// that default. JDK 1.2 doc infers not to do a bind.
impl.connect(address, port);
} }
/**
* Initializes a new instance of <code>Socket</code> that connects to the
* named host on the specified port and binds to the specified local address
* and port.
*
* @param host The name of the remote host to connect to.
* @param port The remote port to connect to.
* @param loadAddr The local address to bind to.
* @param localPort The local port to bind to.
*
* @exception SecurityException If the <code>SecurityManager</code>
* exists and does not allow a connection to the specified host/port or
* binding to the specified local host/port.
* @exception IOException If a connection error occurs.
*/
public Socket (String host, int port, public Socket (String host, int port,
InetAddress localAddr, int localPort) throws IOException InetAddress localAddr, int localPort) throws IOException
{ {
this(factory == null ? new PlainSocketImpl() : factory.createSocketImpl()); this(InetAddress.getByName(host), port, localAddr, localPort, true);
SecurityManager s = System.getSecurityManager();
if (s != null)
s.checkConnect(host, port);
impl.create(true);
// FIXME: JCL p. 1587 says if localAddr is null, use getLocalAddress().
impl.bind(localAddr, localPort);
impl.connect(host, port);
} }
/**
* Initializes a new instance of <code>Socket</code> and connects to the
* address and port number specified as arguments, plus binds to the
* specified local address and port.
*
* @param address The remote address to connect to
* @param port The remote port to connect to
* @param localAddr The local address to connect to
* @param localPort The local port to connect to
*
* @exception IOException If an error occurs
*/
public Socket (InetAddress address, int port, public Socket (InetAddress address, int port,
InetAddress localAddr, int localPort) throws IOException InetAddress localAddr, int localPort) throws IOException
{ {
this(factory == null ? new PlainSocketImpl() : factory.createSocketImpl()); this(address, port, localAddr, localPort, true);
SecurityManager s = System.getSecurityManager();
if (s != null)
s.checkConnect(address.getHostName(), port);
impl.create(true);
// FIXME: JCL p. 1587 says if localAddr is null, use getLocalAddress().
impl.bind(localAddr, localPort);
impl.connect(address, port);
} }
/** /**
* @deprecated Use DatagramSocket instead for UDP transport. * Initializes a new instance of <code>Socket</code> and connects to the
* hostname and port specified as arguments. If the stream argument is set
* to <code>true</code>, then a stream socket is created. If it is
* <code>false</code>, a datagram socket is created.
*
* @param host The name of the host to connect to
* @param port The port to connect to
* @param stream <code>true</code> for a stream socket, <code>false</code>
* for a datagram socket
*
* @exception IOException If an error occurs
*
* @deprecated Use the <code>DatagramSocket</code> class to create
* datagram oriented sockets.
*/ */
public Socket (String host, int port, boolean stream) throws IOException public Socket (String host, int port, boolean stream) throws IOException
{ {
impl = factory == null ? new PlainSocketImpl() this(InetAddress.getByName(host), port, null, 0, stream);
: factory.createSocketImpl();
impl.create(stream);
SecurityManager s = System.getSecurityManager();
if (s != null)
s.checkConnect(host, port);
// FIXME: JCL p. 1586 says if localPort is unspecified, bind to any port,
// i.e. '0' and if localAddr is unspecified, use getLocalAddress() as
// that default. JDK 1.2 doc infers not to do a bind.
impl.connect(host, port);
} }
/** /**
* @deprecated Use DatagramSocket instead for UDP transport. * Initializes a new instance of <code>Socket</code> and connects to the
* address and port number specified as arguments. If the stream param is
* <code>true</code>, a stream socket will be created, otherwise a datagram
* socket is created.
*
* @param host The address to connect to
* @param port The port number to connect to
* @param stream <code>true</code> to create a stream socket,
* <code>false</code> to create a datagram socket.
*
* @exception IOException If an error occurs
*
* @deprecated Use the <code>DatagramSocket</code> class to create
* datagram oriented sockets.
*/ */
public Socket (InetAddress host, int port, boolean stream) throws IOException public Socket (InetAddress host, int port, boolean stream) throws IOException
{ {
impl = factory == null ? new PlainSocketImpl() this(host, port, null, 0, stream);
: factory.createSocketImpl(); }
/**
* This constructor is where the real work takes place. Connect to the
* specified address and port. Use default local values if not specified,
* otherwise use the local host and port passed in. Create as stream or
* datagram based on "stream" argument.
* <p>
*
* @param raddr The remote address to connect to
* @param rport The remote port to connect to
* @param laddr The local address to connect to
* @param lport The local port to connect to
* @param stream true for a stream socket, false for a datagram socket
*
* @exception IOException If an error occurs
*/
private Socket(InetAddress raddr, int rport, InetAddress laddr, int lport,
boolean stream) throws IOException
{
this();
if (impl == null)
throw new IOException("Cannot initialize Socket implementation");
SecurityManager sm = System.getSecurityManager();
if (sm != null)
sm.checkConnect(raddr.getHostName(), rport);
impl.create(stream); impl.create(stream);
SecurityManager s = System.getSecurityManager();
if (s != null)
s.checkConnect(host.getHostName(), port);
// FIXME: JCL p. 1586 says if localPort is unspecified, bind to any port, // FIXME: JCL p. 1586 says if localPort is unspecified, bind to any port,
// i.e. '0' and if localAddr is unspecified, use getLocalAddress() as // i.e. '0' and if localAddr is unspecified, use getLocalAddress() as
// that default. JDK 1.2 doc infers not to do a bind. // that default. JDK 1.2 doc infers not to do a bind.
impl.connect(host, port); if (laddr != null)
impl.bind(laddr, lport);
if (raddr != null)
impl.connect(raddr, rport);
} }
/**
* Returns the address of the remote end of the socket. If this socket
* is not connected, then <code>null</code> is returned.
*
* @return The remote address this socket is connected to
*/
public InetAddress getInetAddress () public InetAddress getInetAddress ()
{ {
return impl.getInetAddress(); if (impl != null)
return impl.getInetAddress();
return null;
} }
/**
* Returns the local address to which this socket is bound. If this socket
* is not connected, then <code>null</code> is returned.
*
* @return The local address
*/
public InetAddress getLocalAddress () public InetAddress getLocalAddress ()
{ {
// FIXME: see note in DatagramSocket.java about checkConnect() and security if (impl == null)
return null;
InetAddress addr = null;
try try
{ {
return (InetAddress)impl.getOption(SocketOptions.SO_BINDADDR); addr = (InetAddress)impl.getOption(SocketOptions.SO_BINDADDR);
} }
catch (SocketException x) catch(SocketException e)
{ {
// (hopefully) shouldn't happen // (hopefully) shouldn't happen
System.err.println(x); // throw new java.lang.InternalError
throw new java.lang.InternalError("Error in PlainSocketImpl.getOption"); // ("Error in PlainSocketImpl.getOption");
return null;
} }
// FIXME: According to libgcj, checkConnect() is supposed to be called
// before performing this operation. Problems: 1) We don't have the
// addr until after we do it, so we do a post check. 2). The docs I
// see don't require this in the Socket case, only DatagramSocket, but
// we'll assume they mean both.
SecurityManager sm = System.getSecurityManager();
if (sm != null)
sm.checkConnect(addr.getHostName(), getLocalPort());
return addr;
} }
/**
* Returns the port number of the remote end of the socket connection. If
* this socket is not connected, then -1 is returned.
*
* @return The remote port this socket is connected to
*/
public int getPort () public int getPort ()
{ {
return impl.getPort(); if (impl != null)
return impl.getPort();
return -1;
} }
/**
* Returns the local port number to which this socket is bound. If this
* socket is not connected, then -1 is returned.
*
* @return The local port
*/
public int getLocalPort () public int getLocalPort ()
{ {
return impl.getLocalPort(); if (impl != null)
return impl.getLocalPort();
return -1;
} }
/**
* Returns an InputStream for reading from this socket.
*
* @return The InputStream object
*
* @exception IOException If an error occurs or Socket is not connected
*/
public InputStream getInputStream () throws IOException public InputStream getInputStream () throws IOException
{ {
return impl.getInputStream(); if (impl != null)
return(impl.getInputStream());
throw new IOException("Not connected");
} }
/**
* Returns an OutputStream for writing to this socket.
*
* @return The OutputStream object
*
* @exception IOException If an error occurs or Socket is not connected
*/
public OutputStream getOutputStream () throws IOException public OutputStream getOutputStream () throws IOException
{ {
return impl.getOutputStream(); if (impl != null)
return impl.getOutputStream();
throw new IOException("Not connected");
} }
/**
* Sets the TCP_NODELAY option on the socket.
*
* @param on true to enable, false to disable
*
* @exception SocketException If an error occurs or Socket is not connected
*/
public void setTcpNoDelay (boolean on) throws SocketException public void setTcpNoDelay (boolean on) throws SocketException
{ {
impl.setOption( SocketOptions.TCP_NODELAY, new Boolean(on) ); if (impl == null)
throw new SocketException("Not connected");
impl.setOption(SocketOptions.TCP_NODELAY, new Boolean(on));
} }
/**
* Tests whether or not the TCP_NODELAY option is set on the socket.
* Returns true if enabled, false if disabled. When on it disables the
* Nagle algorithm which means that packets are always send immediatly and
* never merged together to reduce network trafic.
*
* @return Whether or not TCP_NODELAY is set
*
* @exception SocketException If an error occurs or Socket not connected
*/
public boolean getTcpNoDelay() throws SocketException public boolean getTcpNoDelay() throws SocketException
{ {
Boolean bool = (Boolean)impl.getOption( SocketOptions.TCP_NODELAY ); if (impl == null)
return bool.booleanValue(); throw new SocketException("Not connected");
Object on = impl.getOption(SocketOptions.TCP_NODELAY);
if (on instanceof Boolean)
return(((Boolean)on).booleanValue());
else
throw new SocketException("Internal Error");
} }
/**
* Sets the value of the SO_LINGER option on the socket. If the
* SO_LINGER option is set on a socket and there is still data waiting to
* be sent when the socket is closed, then the close operation will block
* until either that data is delivered or until the timeout period
* expires. The linger interval is specified in hundreths of a second
* (platform specific?)
*
* @param on true to enable SO_LINGER, false to disable
* @param linger The SO_LINGER timeout in hundreths of a second or -1 if
* SO_LINGER not set.
*
* @exception SocketException If an error occurs or Socket not connected
*/
public void setSoLinger(boolean on, int linger) throws SocketException public void setSoLinger(boolean on, int linger) throws SocketException
{ {
if ( on && (linger >= 0) ) if (impl == null)
throw new SocketException("No socket created");
if (on == true)
{ {
if (linger > 65535) if (linger < 0)
linger = 65535; throw new IllegalArgumentException("SO_LINGER must be >= 0");
impl.setOption( SocketOptions.SO_LINGER, new Integer(linger) );
} if (linger > 65535)
else if ( on && (linger < 0) ) linger = 65535;
throw new IllegalArgumentException("SO_LINGER must be >= 0");
impl.setOption(SocketOptions.SO_LINGER, new Integer(linger));
}
else else
impl.setOption( SocketOptions.SO_LINGER, new Boolean(false) ); {
impl.setOption(SocketOptions.SO_LINGER, new Boolean(false));
}
} }
/**
* Returns the value of the SO_LINGER option on the socket. If the
* SO_LINGER option is set on a socket and there is still data waiting to
* be sent when the socket is closed, then the close operation will block
* until either that data is delivered or until the timeout period
* expires. This method either returns the timeouts (in hundredths of
* of a second (platform specific?)) if SO_LINGER is set, or -1 if
* SO_LINGER is not set.
*
* @return The SO_LINGER timeout in hundreths of a second or -1
* if SO_LINGER not set
*
* @exception SocketException If an error occurs or Socket is not connected
*/
public int getSoLinger() throws SocketException public int getSoLinger() throws SocketException
{ {
Object linger = impl.getOption(SocketOptions.SO_LINGER); if (impl == null)
if (linger instanceof Integer) throw new SocketException("Not connected");
return ((Integer)linger).intValue();
Object linger = impl.getOption(SocketOptions.SO_LINGER);
if (linger instanceof Integer)
return(((Integer)linger).intValue());
else else
return -1; return -1;
} }
/**
* Sets the value of the SO_TIMEOUT option on the socket. If this value
* is set, and an read/write is performed that does not complete within
* the timeout period, a short count is returned (or an EWOULDBLOCK signal
* would be sent in Unix if no data had been read). A value of 0 for
* this option implies that there is no timeout (ie, operations will
* block forever). On systems that have separate read and write timeout
* values, this method returns the read timeout. This
* value is in thousandths of a second (****????*****)
*
* @param timeout The length of the timeout in thousandth's of a second or
* 0 if not set
*
* @exception SocketException If an error occurs or Socket not connected
*/
public synchronized void setSoTimeout (int timeout) throws SocketException public synchronized void setSoTimeout (int timeout) throws SocketException
{ {
if (impl == null)
throw new SocketException("Not connected");
if (timeout < 0) if (timeout < 0)
throw new IllegalArgumentException("Invalid timeout: " + timeout); throw new IllegalArgumentException("SO_TIMEOUT value must be >= 0");
impl.setOption(SocketOptions.SO_TIMEOUT, new Integer(timeout)); impl.setOption(SocketOptions.SO_TIMEOUT, new Integer(timeout));
} }
/**
* Returns the value of the SO_TIMEOUT option on the socket. If this value
* is set, and an read/write is performed that does not complete within
* the timeout period, a short count is returned (or an EWOULDBLOCK signal
* would be sent in Unix if no data had been read). A value of 0 for
* this option implies that there is no timeout (ie, operations will
* block forever). On systems that have separate read and write timeout
* values, this method returns the read timeout. This
* value is in thousandths of a second (implementation specific?).
*
* @return The length of the timeout in thousandth's of a second or 0
* if not set
*
* @exception SocketException If an error occurs or Socket not connected
*/
public synchronized int getSoTimeout () throws SocketException public synchronized int getSoTimeout () throws SocketException
{ {
if (impl == null)
throw new SocketException("Not connected");
Object timeout = impl.getOption(SocketOptions.SO_TIMEOUT); Object timeout = impl.getOption(SocketOptions.SO_TIMEOUT);
if (timeout instanceof Integer) if (timeout instanceof Integer)
return ((Integer)timeout).intValue(); return(((Integer)timeout).intValue());
else else
return 0; return 0;
} }
// JDK1.2 /**
* This method sets the value for the system level socket option
* SO_SNDBUF to the specified value. Note that valid values for this
* option are specific to a given operating system.
*
* @param size The new send buffer size.
*
* @exception SocketException If an error occurs or Socket not connected
*
* @since Java 1.2
*/
public void setSendBufferSize (int size) throws SocketException public void setSendBufferSize (int size) throws SocketException
{ {
if (impl == null)
throw new SocketException("Not connected");
if (size <= 0) if (size <= 0)
throw new IllegalArgumentException("Invalid buffer size: " + size); throw new IllegalArgumentException("SO_SNDBUF value must be > 0");
impl.setOption(SocketOptions.SO_SNDBUF, new Integer(size)); impl.setOption(SocketOptions.SO_SNDBUF, new Integer(size));
} }
// JDK1.2 /**
* This method returns the value of the system level socket option
* SO_SNDBUF, which is used by the operating system to tune buffer
* sizes for data transfers.
*
* @return The send buffer size.
*
* @exception SocketException If an error occurs or socket not connected
*
* @since Java 1.2
*/
public int getSendBufferSize () throws SocketException public int getSendBufferSize () throws SocketException
{ {
Integer buf = (Integer)impl.getOption(SocketOptions.SO_SNDBUF); if (impl == null)
return buf.intValue(); throw new SocketException("Not connected");
Object buf = impl.getOption(SocketOptions.SO_SNDBUF);
if (buf instanceof Integer)
return(((Integer)buf).intValue());
else
throw new SocketException("Internal Error: Unexpected type");
} }
// JDK1.2 /**
* This method sets the value for the system level socket option
* SO_RCVBUF to the specified value. Note that valid values for this
* option are specific to a given operating system.
*
* @param size The new receive buffer size.
*
* @exception SocketException If an error occurs or Socket is not connected
*
* @since Java 1.2
*/
public void setReceiveBufferSize (int size) throws SocketException public void setReceiveBufferSize (int size) throws SocketException
{ {
if (size <= 0) if (impl == null)
throw new IllegalArgumentException("Invalid buffer size: " + size); throw new SocketException("Not connected");
if (size <= 0)
throw new IllegalArgumentException("SO_RCVBUF value must be > 0");
impl.setOption(SocketOptions.SO_RCVBUF, new Integer(size)); impl.setOption(SocketOptions.SO_RCVBUF, new Integer(size));
} }
// JDK1.2 /**
* This method returns the value of the system level socket option
* SO_RCVBUF, which is used by the operating system to tune buffer
* sizes for data transfers.
*
* @return The receive buffer size.
*
* @exception SocketException If an error occurs or Socket is not connected
*
* @since Java 1.2
*/
public int getReceiveBufferSize () throws SocketException public int getReceiveBufferSize () throws SocketException
{ {
Integer buf = (Integer)impl.getOption(SocketOptions.SO_RCVBUF); if (impl == null)
return buf.intValue(); throw new SocketException("Not connected");
Object buf = impl.getOption(SocketOptions.SO_RCVBUF);
if (buf instanceof Integer)
return(((Integer)buf).intValue());
else
throw new SocketException("Internal Error: Unexpected type");
} }
/**
* Closes the socket.
*
* @exception IOException If an error occurs
*/
public synchronized void close () throws IOException public synchronized void close () throws IOException
{ {
impl.close(); if (impl != null)
impl.close();
} }
/**
* Converts this <code>Socket</code> to a <code>String</code>.
*
* @return The <code>String</code> representation of this <code>Socket</code>
*/
public String toString () public String toString ()
{ {
return "Socket" + impl.toString(); return("Socket " + impl);
} }
// Class Methods
/**
* Sets the <code>SocketImplFactory</code>. This may be done only once per
* virtual machine. Subsequent attempts will generate a
* <code>SocketException</code>. Note that a <code>SecurityManager</code>
* check is made prior to setting the factory. If
* insufficient privileges exist to set the factory, then an
* <code>IOException</code> will be thrown.
*
* @exception SecurityException If the <code>SecurityManager</code> does
* not allow this operation.
* @exception SocketException If the SocketImplFactory is already defined
* @exception IOException If any other error occurs
*/
public static synchronized void setSocketImplFactory (SocketImplFactory fac) public static synchronized void setSocketImplFactory (SocketImplFactory fac)
throws IOException throws IOException
{ {
// See if already set
if (factory != null)
throw new SocketException("SocketImplFactory already defined");
// Check permissions
SecurityManager sm = System.getSecurityManager();
if (sm != null)
sm.checkSetFactory();
factory = fac; factory = fac;
} }
} }