java的URL和Socket区别_UrlConnection连接和Socket连接的区别

关于UrlConnection连接和Socket连接的区别,只知道其中的原理如下:

抽象一点的说,Socket只是一个供上层调用的抽象接口,隐躲了传输层协议的细节。

urlconnection 基于Http协议,Http协议是应用层协议,对传输层Tcp协议进行了封装,是无状态协议,不需要你往考虑线程、同步、状态治理等,

内部是通过socket进行连接和收发数据的,不过一般在数据传输完成之后需要封闭socket连接。

直接使用Socket进行网络通讯得考虑线程治理、客户状态监控等,但是不用发送头信息等,更省流量。

并不知道我们经常使用的URLConnection 内部是怎么实现的,今天心血来潮以URL为出发点来探个究竟。

以下面这段代码为出发点

URL url = new URL("http://zhoujianghai.iteye.com");

URLConnection conecttion = (URLConnection)url.openConnection();

根据java.net.URL源码,一步步进行分析,

new URL("www.javaeye.com")会调用URL(URL context, String spec, URLStreamHandler handler),

此时context和handler是null。

url.openConnection()调用的是strmHandler.openConnection(this);

而strmHandler是URLStreamHandler接口的子类的实例。

抽象类 URLStreamHandler 是所有流协议处理程序的通用超类,可以通过不同 protocol 的 URL 实例,产生 java.net.URLConnection 对象。

由于context和handler是null,所以终极根据具体的协议调用URL类中的setupStreamHandler()方法对strmHandler进行初始化。

下面分析 setupStreamHandler()方法内的代码。

?

?

String packageList = AccessController.doPrivileged(new PriviAction(

"java.protocol.handler.pkgs"));

?

?

首先通过java.protocol.handler.pkgs 来设置 URLStreamHandler 实现类的包路径,SUN 的 JDK 内部实现类均是在 sun.net.www.protocol. 包下。

关于sun/net/www/protocol/http包下相关类的源码,可以访问:http://www.docjar.org/docs/api/sun/net/www/protocol/http/package-index.html

PriviAction 部分源码:

public PriviAction(String property) {

action = GET_SYSTEM_PROPERTY;

arg1 = property;

}

public T run() {

switch (action) {

case GET_SYSTEM_PROPERTY:

return (T)System.getProperty((String) arg1, (String) arg2);

case GET_SECURITY_PROPERTY:

return (T)Security.getProperty((String) arg1);

case GET_SECURITY_POLICY:

return (T)Policy.getPolicy();

case SET_ACCESSIBLE:

((AccessibleObject) arg1).setAccessible(true);

}

return null;

}

PriviAction 实现了 java.security.PrivilegedAction接口,会执行run()方法。

由action = GET_SYSTEM_PROPERTY;可知会执行代码:

(T)System.getProperty((String) arg1, (String) arg2);

System.getProperty方法调用成员变量Properties props的getProperty(key, def)方法;

由于并未设置任何Properties,此处会返回默认值def。def的值是null。

因此会继续执行下面的代码:

String className = "org.apache.harmony.luni.internal.net.www.protocol." + protocol

+ ".Handler";

try {

strmHandler = (URLStreamHandler) Class.forName(className)

.newInstance();

} catch (IllegalAccessException e) {

} catch (InstantiationException e) {

} catch (ClassNotFoundException e) {

}

此时protocol是http协议,从而根据协议 (protocol) 获得协议 URLStreamHandler 对象。

所以此时通过反射机制创建org.apache.harmony.luni.internal.net.www.protocol.http.Handler类的实例。

此时回到上面提到的 strmHandler.openConnection(this);

将调用下面的Handler类的实例的openConnection(URL u)方法。

protected URLConnection openConnection(URL u) throws IOException {

return new HttpURLConnectionImpl(u, getDefaultPort());

}

ected URLConnection openConnection(URL u, Proxy proxy)

throws IOException {

if (null == u || null == proxy) {

throw new IllegalArgumentException(Messages.getString("luni.1B"));

}

return new HttpURLConnectionImpl(u, getDefaultPort(), proxy);

}

此时会创建HttpURLConnectionImpl对象。HttpURLConnectionImpl是java.net.HttpURLConnection的子类。 该类有个成员变量

HttpConnection connection;这才是我们要找的,该类对Socket进行了封装。

HttpConnection 部分源码如下:

private Socket socket;

private SSLSocket sslSocket;

private InputStream inputStream;

private OutputStream outputStream;

private InputStream sslInputStream;

private OutputStream sslOutputStream;

private HttpConfiguration config;

public HttpConnection(HttpConfiguration config, int connectTimeout) throws IOException {

this.config = config;

String hostName = config.getHostName();

int hostPort = config.getHostPort();

Proxy proxy = config.getProxy();

if(proxy == null || proxy.type() == Proxy.Type.HTTP) {

socket = new Socket();

} else {

socket = new Socket(proxy);

}

socket.connect(new InetSocketAddress(hostName, hostPort), connectTimeout);

}

现在UrlConnection连接和Socket连接的区别应该十分清楚了吧。

使用UrlConnection比直接使用Socket要简单的多,不用关心状态和线程治理。

UrlConnection基于Http协议,只是进行了封装,添加了一些额外规则(如头信息),本质上也是建立TCP连接,利用Socket

实现连接和传输数据的,不过我们一般每次请求完数据后都会实现finally方法,在该方法里封闭连接。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值