`
2277259257
  • 浏览: 498406 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

URLConnection/HttpURLConnection/HttpClient/socket 区别

 
阅读更多

 

 

一、介绍

HttpURLConnection是URLConnection的子类,都是Sun公司Java的标准库类,什么都没封装,用起来很原始,若需要高级功能,则会显得不太方便,比如重访问的自定义,会话和cookie等一些高级功能;

这两种方式都支持HTTPS协议,以流的形式进行上传和下载,配置超时时间,IPV6,连接池等功能。

 

HttpClient是Apache公司提供的库,提供高效的、最新的、功能丰富的支持HTTP协议工具包,支持HTTP协议最新的版本和建议,是个很不错的开源框架,封装了http的请求,参数,内容体,响应等,拥有众多API

(提供了执行请求、用工具封装Get请求、处理头部消息、请求HTTP实体/获得HTTP实体/处理HTTP实体/模拟HTML表单、响应处理器、连接管理、状态管理、认证管理、客户服务等)

 

Socket是支持TCP/IP协议的网络通信基本操作单元,是操作系统为应用程序提供的一套针对TCP或UDP的编程接口(API)

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

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

 

 

                  HTML->浏览器自动构建HTTP协议数据格式

数据载体-->XML-->URL.../Http../HttpClient(应用层API)自定义构建HTTP数据格式--> socket(传输层API)

                 JOSN-->URL.../Http../HttpClient(应用层API)自定义构建HTTP数据格式

 

 

 二、应用介绍

 

HttpURLConnection继承自URLConnection,差别在与HttpURLConnection仅仅针对Http连接

 基本步骤:
         1) 创建 URL 以及 URLConnection / HttpURLConnection 对象
         2) 设置连接参数
         3) 连接到服务器
         4) 向服务器写数据
         5)从服务器读取数据

  public void urlConnection()
   {
	String urltext = "";
	try {
//	方法一:
	   URL url = new URL(urltext);
	   URLConnection conn = url.openConnection();//取得一个新的链接对指定的URL
	   conn.connect();//本方法不会自动重连
	   InputStream is = conn.getInputStream();
	   is.close();//关闭InputStream
//	方法二:
	   URL url2 = new URL(urltext);
	   InputStream is2 = url2.openStream();
	   is2.close();//关闭InputStream
	   //URL对象也提供取得InputStream的方法。URL.openStream()会打开自动链接,所以不需要运行openConnection

	//方法三:本方法同一,但是openConnection返回值直接转为HttpsURLConnection,
           //这样可以使用一些Http连接特有的方法,如setRequestMethod
	   URL url3 = new URL(urltext);
	   HttpsURLConnection conn3 =(HttpsURLConnection)url.openConnection();
	   conn3.setRequestMethod("POST");
	   //允许Input、Output,不使用Cache
	   conn3.setDoInput(true);
	   conn3.setDoOutput(true);
	   conn3.setUseCaches(false);
	   /*
	    * setRequestProperty
	    */
	   conn3.setRequestProperty("Connection", "Keep-Alive");
	   conn3.setRequestProperty("Charset", "UTF-8");
	   conn3.setRequestProperty("Content-type", "multipart/form-data;boundary=*****");
	   //在与服务器连接之前,设置一些网络参数
	   conn3.setConnectTimeout(10000);
		  
	   conn3.connect();
           // 与服务器交互:向服务器端写数据,这里可以上传文件等多个操作
	   OutputStream outStream = conn3.getOutputStream();
	   ObjectOutputStream objOutput = new ObjectOutputStream(outStream);
	   objOutput.writeObject(new String("this is a string…"));
	   objOutput.flush();
	
	   // 处理数据, 取得响应内容
	   InputStream is3 = conn.getInputStream();
	   is3.close();//关闭InputStream
	} catch (IOException e) {
           // TODO Auto-generated catch block
	   e.printStackTrace();
	}
   }

 

三、HttpURLConnection用法详解

 

URLConnection的对象问题:
URL url = new URL("http://localhost:8080/TestHttpURLConnectionPro/index.jsp");   
   
URLConnection rulConnection = url.openConnection();  
        // 此处的urlConnection对象实际上是根据URL的   
          // 请求协议(此处是http)生成的URLConnection类   
          // 的子类HttpURLConnection,故此处最好将其转化   
          // 为HttpURLConnection类型的对象,以便用到   
          // HttpURLConnection更多的API.如下:   
    
HttpURLConnection httpUrlConnection = (HttpURLConnection) rulConnection;

 

HttpURLConnection对象参数问题:
// 设置是否向httpUrlConnection输出,因为这个是post请求,参数要放在   
 // http正文内,因此需要设为true, 默认情况下是false;   
 httpUrlConnection.setDoOutput(true);   
   
 // 设置是否从httpUrlConnection读入,默认情况下是true;   
 httpUrlConnection.setDoInput(true);   
   
 // Post 请求不能使用缓存   
 httpUrlConnection.setUseCaches(false);   
   
 // 设定传送的内容类型是可序列化的java对象   
 // (如果不设此项,在传送序列化对象时,当WEB服务默认的不是这种类型时可能抛java.io.EOFException)   
 httpUrlConnection.setRequestProperty("Content-type", "application/x-java-serialized-object");   
   
 // 设定请求的方法为"POST",默认是GET   
 httpUrlConnection.setRequestMethod("POST");   
   
 // 连接,从上述第2条中url.openConnection()至此的配置必须要在connect之前完成,   
         httpUrlConnection.connect();

 

HttpURLConnection连接问题:
// 此处getOutputStream会隐含的进行connect(即:如同调用上面的connect()方法,   
// 所以在开发中不调用上述的connect()也可以)。   
    OutputStream outStrm = httpUrlConnection.getOutputStream();

 

HttpURLConnection写数据与发送数据问题:
   // 现在通过输出流对象构建对象输出流对象,以实现输出可序列化的对象。   
    ObjectOutputStream objOutputStrm = new ObjectOutputStream(outStrm);   
     
   // 向对象输出流写出数据,这些数据将存到内存缓冲区中   
    objOutputStrm.writeObject(new String("我是测试数据"));   
     
   // 刷新对象输出流,将任何字节都写入潜在的流中(些处为ObjectOutputStream)   
    objOutputStm.flush();   
     
   // 关闭流对象。此时,不能再向对象输出流写入任何数据,先前写入的数据存在于内存缓冲区中,   
   // 在调用下边的getInputStream()函数时才把准备好的http请求正式发送到服务器   
   objOutputStm.close();   
     
   // 调用HttpURLConnection连接对象的getInputStream()函数,   
   // 将内存缓冲区中封装好的完整的HTTP请求电文发送到服务端。   
   InputStream inStrm = httpConn.getInputStream(); // <===注意,实际发送请求的代码段就在这里   
     
  // 上边的httpConn.getInputStream()方法已调用,本次HTTP请求已结束,下边向对象输出流的输出已无意义,   
  // 既使对象输出流没有调用close()方法,下边的操作也不会向对象输出流写入任何数据.   
  // 因此,要重新发送数据时需要重新创建连接、重新设参数、重新创建流对象、重新写数据、   
  // 重新发送数据(至于是否不用重新这些操作需要再研究)   
    objOutputStm.writeObject(new String(""));   
    httpConn.getInputStream()

 总结

    a:) HttpURLConnection的connect()函数,实际上只是建立了一个与服务器的tcp连接,并没有实际发送http请求。 

    无论是post还是get,http请求实际上直到HttpURLConnection的getInputStream()这个函数里面才正式发送出去。 
    b:) 在用POST方式发送URL请求时,URL请求参数的设定顺序是重中之重, 
    对connection对象的一切配置(那一堆set函数) 
    都必须要在connect()函数执行之前完成。而对outputStream的写操作,又必须要在inputStream的读操作之前。 
    这些顺序实际上是由http请求的格式决定的。 
    如果inputStream读操作在outputStream的写操作之前,会抛出例外: 
    java.net.ProtocolException: Cannot write output after reading input....... 
    c:) http请求实际上由两部分组成, 
    一个是http头,所有关于此次http请求的配置都在http头里面定义, 
           一个是正文content。 
    connect()函数会根据HttpURLConnection对象的配置值生成http头部信息,因此在调用connect函数之前, 
    就必须把所有的配置准备好。 
    d:) 在http头后面紧跟着的是http请求的正文,正文的内容是通过outputStream流写入的, 
    实际上outputStream不是一个网络流,充其量是个字符串流,往里面写入的东西不会立即发送到网络, 
    而是存在于内存缓冲区中,待outputStream流关闭时,根据输入的内容生成http正文。 
    至此,http请求的东西已经全部准备就绪。在getInputStream()函数调用的时候,就会把准备好的http请求 
    正式发送到服务器了,然后返回一个输入流,用于读取服务器对于此次http请求的返回信息。由于http 
    请求在getInputStream的时候已经发送出去了(包括http头和正文),因此在getInputStream()函数 
    之后对connection对象进行设置(对http头的信息进行修改)或者写入outputStream(对正文进行修改) 
    都是没有意义的了,执行这些操作会导致异常的发生。 

7:> Servlet端的开发注意点: 
    a:) 对于客户端发送的POST类型的HTTP请求,Servlet必须实现doPost方法,而不能用doGet方法。 
    b:) 用HttpServletRequest的getInputStream()方法取得InputStream的对象,比如: 
     InputStream inStream = httpRequest.getInputStream(); 
     现在调用inStream.available()(该方法用于“返回此输入流下一个方法调用可以不受阻塞地 
     从此输入流读取(或跳过)的估计字节数”)时,永远都反回0。试图使用此方法的返回值分配缓冲区, 
     以保存此流所有数据的做法是不正确的。那么,现在的解决办法是 
     Servlet这一端用如下实现: 
     InputStream inStream = httpRequest.getInputStream(); 
     ObjectInputStream objInStream = new ObjectInputStream(inStream); 
     Object obj = objInStream.readObject(); 
     // 做后续的处理 
     // 。。。。。。 
     // 。。。 。。。 
     而客户端,无论是否发送实际数据都要写入一个对象(那怕这个对象不用),如: 
     ObjectOutputStream objOutputStrm = new ObjectOutputStream(outStrm); 
     objOutputStrm.writeObject(new String("")); // 这里发送一个空数据 
     // 甚至可以发一个null对象,服务端取到后再做判断处理。 
     objOutputStrm.writeObject(null); 
     objOutputStrm.flush(); 
     objOutputStrm.close(); 

注意:上述在创建对象输出流ObjectOutputStream时,如果将从HttpServletRequest取得的输入流 
      (即:new ObjectOutputStream(outStrm)中的outStrm)包装在BufferedOutputStream流里面, 
      则必须有objOutputStrm.flush();这一句,以便将流信息刷入缓冲输出流.如下: 
      ObjectOutputStream objOutputStrm = new ObjectOutputStream(new BufferedOutputStream(outStrm)); 
      objOutputStrm.writeObject(null); 
      objOutputStrm.flush(); // <======此处必须要有. 
      objOutputStrm.close(); 

    HttpURLConnection是基于HTTP协议的,其底层通过socket通信实现。如果不设置超时(timeout),在网络异常的情况下,可能会导致程序僵死而不继续往下执行。可以通过以下两个语句来设置相应的超时: 
System.setProperty("sun.net.client.defaultConnectTimeout", 超时毫秒数字符串); 
System.setProperty("sun.net.client.defaultReadTimeout", 超时毫秒数字符串); 


其中: sun.net.client.defaultConnectTimeout:连接主机的超时时间(单位:毫秒) 
sun.net.client.defaultReadTimeout:从主机读取数据的超时时间(单位:毫秒) 

例如: 
System.setProperty("sun.net.client.defaultConnectTimeout", "30000"); 
System.setProperty("sun.net.client.defaultReadTime 

Java中可以使用HttpURLConnection来请求WEB资源。 
HttpURLConnection对象不能直接构造,需要通过URL.openConnection()来获得HttpURLConnection对象,示例代码如下: 

1
2
3
 String szUrl = "http://www.ee2ee.com/";  
 URL url = new URL(szUrl);  
 HttpURLConnection urlCon = (HttpURLConnection)url.openConnection();

HttpURLConnection是基于HTTP协议的,其底层通过socket通信实现。如果不设置超时(timeout),在网络异常的情况下,可能会导致程序僵死而不继续往下执行。可以通过以下两个语句来设置相应的超时: 
System.setProperty("sun.net.client.defaultConnectTimeout", 超时毫秒数字符串); 
System.setProperty("sun.net.client.defaultReadTimeout", 超时毫秒数字符串); 


其中: sun.net.client.defaultConnectTimeout:连接主机的超时时间(单位:毫秒) 
sun.net.client.defaultReadTimeout:从主机读取数据的超时时间(单位:毫秒) 

例如: 
System.setProperty("sun.net.client.defaultConnectTimeout", "30000"); 
System.setProperty("sun.net.client.defaultReadTimeout", "30000"); 

JDK 1.5以前的版本,只能通过设置这两个系统属性来控制网络超时。在1.5中,还可以使用HttpURLConnection的父类URLConnection的以下两个方法: 
setConnectTimeout:设置连接主机超时(单位:毫秒) 
setReadTimeout:设置从主机读取数据超时(单位:毫秒) 

例如: 

1
2
3
 HttpURLConnection urlCon = (HttpURLConnection)url.openConnection();  
 urlCon.setConnectTimeout(30000);  
 urlCon.setReadTimeout(30000);

需要注意的是,笔者在JDK1.4.2环境下,发现在设置了defaultReadTimeout的情况下,如果发生网络超时,HttpURLConnection会自动重新提交一次请求,出现一次请求调用,请求服务器两次的问题(Trouble)。我认为这是JDK1.4.2的一个bug。在JDK1.5.0中,此问题已得到解决,不存在自动重发现象。out", "3000

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

分享到:
评论

相关推荐

    HttpClient以及获取页面内容应用

    压缩包中含有多个文档,从了解httpclient到应用。 httpClient 1httpClint 1.1简介 HttpClient是Apache Jakarta Common下的子项目,用来提供高效的、最新的、功能丰富的支持HTTP协议的客户端编程工具包,并且它支持...

    疯狂Android讲义(第2版)源代码 第10章~第13章

    13.1、基于TCP协议的网络通信(套接字Socket):Socket; ServerSocket; 13.2、使用URL访问网络资源:URL; URLConnection; 13.3、使用HTTP访问网络:HttpURLConnection; HttpClient; 13.4、使用WebView视图显示网页...

    Android实验七.doc

    Apache、socket、URLConnection、httpConnection。 2. 常用的数据传输格式有哪两种? JSON、XML。 3. Android网络编程必须申请的权限是? ...

    okhttp-2.1.0.jar okip-1.0.1.jar

    1 支持SPDY,允许所有同一主机的...okhttp-urlconnection模块实现了都很熟悉的java.net.HttpURLConnection的API,okhttp-apache模块实现了Apache的HttpClient的API。OKHTTP支持Android2.3以上,Java支持最低版本1.7。

    http_all-2.1.0.jar.zip

    1 支持SPDY,允许所有同一主机的...okhttp-urlconnection模块实现了都很熟悉的java.net.HttpURLConnection的API,okhttp-apache模块实现了Apache的HttpClient的API。OKHTTP支持Android2.3以上,Java支持最低版本1.7。

    Android实例代码

    13.1、基于TCP协议的网络通信(套接字Socket):Socket; ServerSocket; 13.2、使用URL访问网络资源:URL; URLConnection; 13.3、使用HTTP访问网络:HttpURLConnection; HttpClient; 13.4、使用WebView视图显示网页...

    疯狂Android讲义(第2版)源代码 第6章~第9章

    13.1、基于TCP协议的网络通信(套接字Socket):Socket; ServerSocket; 13.2、使用URL访问网络资源:URL; URLConnection; 13.3、使用HTTP访问网络:HttpURLConnection; HttpClient; 13.4、使用WebView视图显示网页...

    疯狂Android讲义源码

     13.3.2 使用Apache HttpClient 501  13.4 使用WebView视图  显示网页 505  13.4.1 使用WebView浏览网页 506  13.4.2 使用WebView加载HTML  代码 507  13.5 使用Web Service进行  网络编程 508  13.5.1 Web...

    疯狂Android讲义.part2

    13.3.2 使用Apache HttpClient 501 13.4 使用WebView视图显示 网页 506 13.4.1 使用WebView浏览网页 506 13.4.2 使用WebView加载HTML 代码 507 13.5 使用Web Service进行网络 编程 508 13.5.1 Web Service简介 509 ...

    疯狂Android讲义.part1

    13.3.2 使用Apache HttpClient 501 13.4 使用WebView视图显示 网页 506 13.4.1 使用WebView浏览网页 506 13.4.2 使用WebView加载HTML 代码 507 13.5 使用Web Service进行网络 编程 508 13.5.1 Web Service简介 509 ...

Global site tag (gtag.js) - Google Analytics