Java中Socket如何获得输入流

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

Socket类是java语言建立网络连接的核心类,通过对指定地址和端口的访问,获得资源的输入流。本文通过对源码分析,简单介绍Socket类的实现。

Socket SocksSocketImpl PlainSocketImpl AbstractPla getInputStream getInputStream getInputStream socketInputStream Socket SocksSocketImpl PlainSocketImpl AbstractPla

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();
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值