————————————————————————————————————————————————
Extending Sockets in JDK 1.1
Some of the improvements to the java.net
classes in JDK 1.1 allow sockets (Socket/ServerSocket) to be non-final, extendable classes. The basic goal is to allow extended sockets to be used whereever a base class Socket is used without rewriting application code. So for example an already-existing email client could be handed a subclass of Socket that does peer authentication or encryption, which the Socket subclass would handle transparently. Other examples include sockets that transparently use compression, or which add functionality such as mirroring traffic to multiple servers (e.g. using reliable ordered multicast).
This document has the following sections:
- JDK 1.0: SocketImpl
- JDK 1.1: Non-Final Socket and ServerSocket Classes
- Socket: How to extend Socket
- ServerSocket: How to extend ServerSocket
JDK 1.0: SocketImpl and SocketImplFactory
JDK 1.0 allows licensees to extend socket functionality in one very particular way: they can subclass java.net.SocketImpl
, and provide an enhanced java.net.SocketImplFactory() which returns such classes as needed.
The SocketImpl/SocketImplFactory scheme is useful for, and was designed for, java apps/applications to be portable across environments that use different transport mechanisms. A client application that uses a java.net.Socket can work in the general case (where the runtime uses a PlainSocketImpl), as well as in environments where network connections must do something particular. For example, a java program should be able to work behind a firewall where connections to the Internet must be done through a proxy protocol, like SOCKS, assuming the right kind of SocketImpl is set for the java runtime in that environment.
Though the SocketImpl is useful for things like transparently providing proxy support to java apps, its utility is limited as a way to provide added functionality of network transport, or for layering other protocols on top of TCP. Additionally, it's only possible to have a single type of SocketImpl installed for a java runtime, which limits large-scale applications. It's cleaner and more intuitive to make ServerSocket and Socket extendable.
Note that the SocketImpl mechanism is designed to be orthogonal to the functionality provided by a subclass of Socket: for example, a subclass of Socket that is capable of doing compression on its streams would still want to use the system-default SocketImpl to get proxy support behind certain kinds of firewalls. The system-default SocketImpl can be thought of as an extension of the transport layer that applications needn't be aware of, and subclasses of Socket/ServerSocket provide richer functionality at the application layer.
Change in JDK 1.1
In JDK 1.1, Socket and ServerSocket are made non-final, which is a pretty simple change. The one basic caveat is that subclasses do not have direct access to the underlying SocketImpl in the base classes, primarily for security reasons. But other than that, subclasses of Socket/ServerSocket inherit and can override methods from their superclass.
The JDK changed by:
- Removing the
final
modifier from theSocket
andServerSocket
classes. - Reattaching that
final
modifier only to methods where it is needed to avoid bypassing security manager calls. - Defining a new method in ServerSocket with signature:
protected final void implAccept(Socket client)
to use when initializing a newly accepted socket. - Exposing a default
Socket
constructor so that Socket subclasses could initialize their superclass without doing an actual connection in the superclass. This is also required so that a ServerSocket subclasses can return the correct Socket subclass from accept() (e.g., FooServerSocket.accept() returns a FooSocket)
Changes to Socket
The public constructors to Socket of the general form:
...
}
/* install system-default SocketImpl */
...
}
protected Socket(SocketImpl impl) {
this.impl = impl;
}
Changes to ServerSocket
Subclasses of ServerSocket also have a protected constructor exposed to them that creates a default SocketImpl in the base class, but doesn't otherwise initialize it (e.g., doesn't call impl.create(), impl.bind() or impl.listen()). The public constructors of ServerSocket will initialize the underlying SocketImpl.
/* install system-default SocketImpl */
...
}
...
protected final void implAccept(Socket s) throws IOException {
...
// on return from this call s will be connected to a client
}
...
...
public Socket accept () throws IOException
{
SSLSocket s = new SSLSocket (certChain, privateKey);
// create an unconnected client SSLSocket, that we'll
// return from accept
implAccept (s);
s.handshake ();
return s;
}
...
}
class SSLSocket extends java.net.Socket {
...
public SSLSocket(CertChain c, PrivateKey k) {
super();
...
}
...
}
Last Modified: 21 August, 1996
David Brownell
David Brown