Socket 源码分析
套接字为一个普通的java类,但是它的逻辑实现却主要依赖了一个以SocketImpl抽象类为基类的系列类,并且它的相关逻辑是默认托管给一个SocksSocketImpl(SocketImpl的后代类)的,同时SocksSocketImpl又将主要的逻辑托管给父类,最终由其兄弟类DualStackSocketImpl或者是TwoStackSocketImpl实现核心的业务代码,事实上是调用了native方法。 SocketImpl这个类是套接字的实现类。Impl是套接字的方法的实现。而在Socket套接字类中,里面的构造方法实现了代理和空参构造的生成。构造方法有如下几个构造方法: 1.代理参数构造方法: public Socket(Proxy proxy) { // Create a copy of Proxy as a security measure if (proxy == null) { throw new IllegalArgumentException(“Invalid Proxy”); } Proxy p = proxy == Proxy.NO_PROXY ? Proxy.NO_PROXY : sun.net.ApplicationProxy.create(proxy); Proxy.Type type = p.type(); if (type == Proxy.Type.SOCKS || type == Proxy.Type.HTTP) { SecurityManager security = System.getSecurityManager(); InetSocketAddress epoint = (InetSocketAddress) p.address(); if (epoint.getAddress() != null) { checkAddress (epoint.getAddress(), “Socket”); } if (security != null) { if (epoint.isUnresolved()) epoint = new InetSocketAddress(epoint.getHostName(), epoint.getPort()); if (epoint.isUnresolved()) security.checkConnect(epoint.getHostName(), epoint.getPort()); else security.checkConnect(epoint.getAddress().getHostAddress(), epoint.getPort()); } impl = type == Proxy.Type.SOCKS ? new SocksSocketImpl(p) : new HttpConnectSocketImpl(p); impl.setSocket(this); } else { if (p == Proxy.NO_PROXY) { if (factory == null) { impl = new PlainSocketImpl(); impl.setSocket(this); } else setImpl(); } else throw new IllegalArgumentException(“Invalid Proxy”); }}创建一个未连接的套接字,根据proxy的类型来判断代理的类型。如果proxy的类型是Socks或者Http就根据这个类型来创建代理实现类SocksSocketImpl,HttpConnectSocketImpl。如果是直接连接,就创建一个PlainSocketImpl进行直接连接。 2.无参构造 public Socket() { setImpl();}直接创建一个SocketImpl,设置实现类的地址Socket的默认实现类。 3.根据主机地址和端口来创建一个套接字 public Socket(String host, int port) throws UnknownHostException, IOException { this(host != null ? new InetSocketAddress(host, port) : new InetSocketAddress(InetAddress.getByName(null), port), (SocketAddress) null, true); } 根据主机名和端口号来生成一个InetSocketAddress,通过InetSocketAddress来进行套接字的构造。 4.根据InetSocketAddress和端口号来生成套接字 publi