Socket类是java语言建立网络连接的核心类,通过对指定地址和端口的访问,获得资源的输入流。本文通过对源码分析,简单介绍Socket类的实现。
Java version jdk1.8.0_121
package java.net
Class Socket
public InputStream getInputStream() throws IOException {
if (isClosed())
throw new SocketException("Socket is closed");
if (!isConnected())
throw new SocketException("Socket is not connected");
if (isInputShutdown())
throw new SocketException("Socket input is shutdown");
final Socket s = this;
InputStream is = null;
try {
is = AccessController.doPrivileged(
new PrivilegedExceptionAction<InputStream>() {
public InputStream run() throws IOException {
return impl.getInputStream();
}
});
} catch (java.security.PrivilegedActionException e) {
throw (IOException) e.getException();
}
return is;
}
核心代码如下:
public InputStream run() throws IOException {
return impl.getInputStream();
}
那么impl是什么,又是如何实现的?
SocketImpl impl;
void setImpl() {
if (factory != null) {
impl = factory.createSocketImpl();
checkOldImpl();
} else {
// No need to do a checkOldImpl() here, we know it's an up to date
// SocketImpl!
impl = new SocksSocketImpl();
}
if (impl != null)
impl.setSocket(this);
}
SocksSocketImpl类实例化一个PlainSocketImpl类,并获得其中的输入流。
Class SocksSocketImpl如下:
try {
AccessController.doPrivileged(
new PrivilegedExceptionAction<Void>() {
public Void run() throws Exception {
cmdsock = new Socket(new PlainSocketImpl());
cmdsock.connect(new InetSocketAddress(server, serverPort));
cmdIn = cmdsock.getInputStream();
cmdOut = cmdsock.getOutputStream();
return null;
}
});
}
Class PlainSocketImpl
class PlainSocketImpl extends AbstractPlainSocketImpl
{
private AbstractPlainSocketImpl impl;
PlainSocketImpl() {
if (useDualStackImpl) {
impl = new DualStackPlainSocketImpl(exclusiveBind);
} else {
impl = new TwoStacksPlainSocketImpl(exclusiveBind);
}
}
protected synchronized InputStream getInputStream() throws IOException {
return impl.getInputStream();
}
}
PlainSocketImpl类、DualStackPlainSocketImpl类和TwoStacksPlainSocketImpl类都是AbstractPlainSocketImpl的子类,其中DualStackPlainSocketImpl类和TwoStacksPlainSocketImpl类中都没有getInputStream方法,因此这三个类的getInputStream方法全部继承于AbstractPlainSocketImpl类。
Class AbstractPlainSocketImpl
protected synchronized InputStream getInputStream() throws IOException {
synchronized (fdLock) {
if (isClosedOrPending())
throw new IOException("Socket Closed");
if (shut_rd)
throw new IOException("Socket input is shutdown");
if (socketInputStream == null)
socketInputStream = new SocketInputStream(this);
}
return socketInputStream;
}
getInputStream方法实例化一个SocketInputStream并返回该输入流引用。
Class SocketInputStream
SocketInputStream(AbstractPlainSocketImpl impl) throws IOException {
super(impl.getFileDescriptor());
this.impl = impl;
socket = impl.getSocket();
}
AbstractPlainSocketImpl类中没有getSocket方法,只有子类PlainSocketImpl中有该方法。
Socket getSocket() {
return impl.getSocket();
}

本文深入剖析了Java中Socket类的实现原理,通过源码分析介绍了Socket如何通过指定地址和端口获取资源输入流。详细解释了SocketImpl、SocksSocketImpl、PlainSocketImpl等关键类的作用及其实现细节。
1142

被折叠的 条评论
为什么被折叠?



