網絡相關係列之中的一個:Android中使用HttpClient發送HTTP請求

1、HTTP協議初探:html

HTTP(Hypertext Transfer Protocol)中文 「超文本傳輸協議」,是一種爲分佈式,合做式,多媒體信息系統服務,面向應用層的協議,是Internet上眼下使用最普遍的應用層協議。它基於傳輸層的TCP協議進行通訊,HTTP協議是通用的、無狀態協議。java

這幾個名詞有一種通俗的解釋:android

  • 通信協議:兩方對話的標準
  • 通用的:用了都說好,誰用誰知道
  • 無狀態的:翻臉不認人
  • 超文本:除了文本,還可以是音頻、視頻

HTTP協議與Android開發之間的關係:apache


HTTP協議的學習重點:編程

  • Http協議基礎概念、
  • 請求響應模型、
  • 提交請求的不一樣方法、
  • 響應狀態推斷、
  • 獲取響應以及解析響應、
  • 數據下載的實現方法、
  • 數據上傳的實現方法、
  • 請求頭具體內容、
  • 響應頭具體內容等
2、http協議概念:
一、http協議定義:
WWW是以Internet做爲傳輸媒介的一個應用系統。WWW網上主要的傳輸單位是Web網頁。

WWW的工做是基於客戶機/server計算模型,由Web瀏覽器和Webserver構成,二者之間採用超文本傳輸協議HTTP進行通訊。瀏覽器

這裏我還專門查了一下:
首先必須強調的是C/S和B/S並無本質的差異:B/S是基於特定通訊協議(HTTP)的C/S架構,也就是說B/S包括在C/S中,是特殊的C/S架構。

之因此在C/S架構上提出B/S架構,是爲了知足 瘦client、一體化client的需要,終於目的節約client更新、維護等的成本,及廣域資源的共享。
(1)B/S屬於C/S,瀏覽器僅僅是特殊的client。
(2)C/S可以使用不論什麼 通訊協議,而B/S這個特殊的C/S架構規定必須實現 HTTP協議
(3)瀏覽器是一個通用client,本質上開發瀏覽器。仍是實現一個C/S系統。

HTTP協議時基於TCP/IP協議之上的協議,是Web瀏覽器和Webserver之間的應用層的協議,是通用的、無狀態的面向對象的協議。  
假設要實現網絡互聯咱們要思考兩個需要解決的技術問題:
  • 第一:瀏覽器和server是經過什麼來鏈接的。
  • 第二:這樣的鏈接方式是怎麼實現的。
經過Internet去發送到server其中。而Internet內部可以經過三種方式來實現發送信息和數據:

  • 第一種:HTTP協議。也是在工做中最常用的。是創建在TCP/IP基礎上實現的。
  • 另一種:FTP協議
  • 第三種:TCP/IP協議,它也是最底層的協議族。其餘的方式必須是要經過它,但是要想實現這樣的協議必須要實現socket編程,這樣的方法是用來上傳一些比較大的文件,視頻,進行斷點續傳的操做。

二、client鏈接server實現內部的原理例如如下:
分析上圖,過程例如如下:
  • 第一步:在瀏覽器client中獲得用戶輸入的內容。 
  • 第二步:瀏覽器獲得這個網址以後。內部會將這個域名發送到DNS上,進行域名解析。獲得它的IP以後就會連接到指定的server上,假如server的地址是:221.104.13.32:80。從瀏覽器到serverport它使用到最底層的TCP/IP協議。

     

  • 第三步:實現TCP/IP協議用Socket來完畢。使用了Socket的套接字。 
  • 第四步:server端的80port監聽client的連接,這樣client到server就連接上了。
  • server接收到這些內容以後。並依照這些請求的路徑找到相應的頁面,進一步找到相應的網頁內容,返回給client。
通俗一點講,用戶在瀏覽器輸入網址,經過http協議發出去,網址通過DNS域名解析。解析成指定的ip地址,並在80port上監聽用戶的請求。server監聽到請求以後。會以三種方式返回給client:HTML、XML、JASON。
HTTP返回請求數據的三種方式:
  • 一、以HTML代碼內容返回。 
  • 二、以XML字符串的形式返回,在android開發中這樣的形式返回數據比較多。 
  • 三、以JSON對象形式返回,在網絡流量上考慮JSON要比XML方式要好一些,便於解析。
在Android其中,通常使用xml和Json數據解析。


3、使用HTTP協議訪問網絡:緩存

Android中的WebView控件已經在後臺幫咱們處理好了發送HTTP請求、接收服務響應、解析返回數據,以及終於的頁面展現這幾步工做,只是由於它封裝得太好了,反而不能直觀地看出HTTP協議是怎樣工做的。所以接下來咱們經過手動發送HTTP請求的方式。來更加深刻的瞭解這一過程。網絡

在Android上發送HTTP請求的方式通常有兩種:HttpURLConnectionHttpClient架構

咱們先來學習HttpClient。app


4、HttpCient:

HttpClient是Apache開源組織提供的HTTP網絡訪問接口(一個開源的項目)。從名字上就可以看出。它是一個簡單的HTTPclient(並不是瀏覽器)。可以發送HTTP請求,接受HTTP響應。但是不會緩存server的響應。不能運行HTTP頁面中籤入嵌入的JS代碼天然也不會對頁面內容進行不論什麼解析、處理,這些都是需要開發者來完畢的。

現在Android已經成功集成了HttpClient,因此開發者在Android項目中可以直接使用HttpClient來向Web網站提交請求以及接受響應,假設使用其它的Java項目,需要引入進對應的Jar包。HttpClient可以在官網上下載。

官網連接:http://hc.apache.org/downloads.cgi

HttpClient事實上是一個interface類型,HttpClient封裝了對象需要運行的Http請求、身份驗證、鏈接管理和其餘特性。

既然HttpClient是一個接口,所以沒法建立它的實例。從文檔上看。HttpClient有三個已知的實現類各自是:AbstractHttpClient, AndroidHttpClient, DefaultHttpClient,會發現有一個專門爲Android應用準備的實現類AndroidHttpClient,固然使用常規的DefaultHttpClient也可以實現功能。

從兩個類包所有在位置就可以看出差異,AndroidHttpClient定義在android.net.http.AndroidHttpClient包下,屬於Android原生的http訪問。而DefaultHttpClient定義在org.apache.http.impl.client.DefaultHttpClient包下,屬於對apche項目的支持。

而AndroidHttpClient沒有公開的構造函數,僅僅能經過靜態方法newInstance()方法來得到AndroidHttpClient對象。


簡單來講,用HttpClient發送請求、接收響應都很是easy,僅僅需要五大步驟就能夠:(要牢記)

  • 建立表明client的HttpClient對象。
  • 建立表明請求的對象,假設需要發送GET請求,則建立HttpGet對象,假設需要發送POST請求。則建立HttpPost對象。

    注:對於發送請求的參數,GET和POST使用的方式不一樣。GET方式可以使用拼接字符串的方式。把參數拼接在URL結尾。POST方式需要使用setEntity(HttpEntity entity)方法來設置請求參數。

  • 調用HttpClient對象的execute(HttpUriRequest request)發送請求,運行該方法後將得到server返回的HttpResponse對象。server發還給咱們的數據就在這個HttpResponse響應其中。調用HttpResponse的相應方法獲取server的響應頭、響應內容等。
  • 檢查對應狀態是否正常。server發給client的相響應,有一個響應碼:響應碼爲200。正常;響應碼爲404,client錯誤。響應碼爲505,server端錯誤。
  • 得到響應對象其中的數據

 

5、DefaultHttpClient:

依據上面的五大步驟,咱們就拿DefaultHttpClient舉例來訪問網絡。

注意這裏有一條原則:在主線程中不能訪問網絡(在android4.0以後的增長的概念)。

一個demo:點擊button,獲取百度首頁的文本內容

新建project文件m04_http01。

完整版代碼例如如下:

首先是佈局文件。儘管比較簡單。但仍是貼上吧。

activity_main.xml代碼例如如下:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity" >

    <Button
        android:id="@+id/button1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Send Request" />

    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent" >

        <TextView
            android:id="@+id/TextView1"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@string/hello_world" />
    </ScrollView>

</LinearLayout>

佈局文件裏,咱們用一個ScrollView來包裹TextView。藉助ScrollView控件的話。就可以贊成咱們一滾動的形式查看屏幕外i的那部份內容

MainActivity.java的代碼例如如下:(凝視比較具體)

 package com.example.m04_http01;
  
 import org.apache.http.HttpEntity;
 import org.apache.http.HttpResponse;
 import org.apache.http.client.HttpClient;
 import org.apache.http.client.methods.HttpGet;
 import org.apache.http.impl.client.DefaultHttpClient;
 import org.apache.http.util.EntityUtils;
 import android.app.Activity;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Message;
 import android.view.View;
 import android.view.View.OnClickListener;
 import android.widget.Button;
 import android.widget.TextView;
 
 public class MainActivity extends Activity {
 
     public static final int SHOW_RESPONSE = 0;
     
     private Button button_sendRequest;
     private TextView textView_response;
     
     //新建Handler的對象,在這裏接收Message。而後更新TextView控件的內容
     private Handler handler = new Handler() {
 
         @Override
         public void handleMessage(Message msg) {
             super.handleMessage(msg);
             switch (msg.what) {
             case SHOW_RESPONSE:
                 String response = (String) msg.obj;
                 textView_response.setText(response);
                 break;
 
             default:
                 break;
             }            
         }
 
     };
     
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.activity_main);
         textView_response = (TextView)findViewById(R.id.TextView1);
         button_sendRequest = (Button)findViewById(R.id.button1);
         
         button_sendRequest.setOnClickListener(new OnClickListener() {
             
             //點擊按鈕時。運行sendRequestWithHttpClient()方法裏面的線程
             @Override
             public void onClick(View v) {
                 // TODO Auto-generated method stub
                 sendRequestWithHttpClient();
             }
         });
     }
 
     //方法:發送網絡請求,獲取百度首頁的數據。

在裏面開啓線程 private void sendRequestWithHttpClient() { new Thread(new Runnable() { @Override public void run() { //用HttpClient發送請求,分爲五步 //第一步:建立HttpClient對象 HttpClient httpCient = new DefaultHttpClient(); //第二步:建立表明請求的對象,參數是訪問的server地址 HttpGet httpGet = new HttpGet("http://www.baidu.com"); try { //第三步:運行請求,獲取server發還的響應對象 HttpResponse httpResponse = httpCient.execute(httpGet); //第四步:檢查響應的狀態是否正常:檢查狀態碼的值是200表示正常 if (httpResponse.getStatusLine().getStatusCode() == 200) { //第五步:從對應對象其中取出數據。放到entity其中 HttpEntity entity = httpResponse.getEntity(); String response = EntityUtils.toString(entity,"utf-8");//將entity其中的數據轉換爲字符串 //在子線程中將Message對象發出去 Message message = new Message(); message.what = SHOW_RESPONSE; message.obj = response.toString(); handler.sendMessage(message); } } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } }).start();//這個start()方法不要忘記了 } }

最後要記得在清單文件裏聲明訪問網絡的權限:
<uses-sdk

android:minSdkVersion="8"

android:targetSdkVersion="16" />

<uses-permission android:name="android.permission.INTERNET"/>
程序執行後,點擊button,顯示結果例如如下:
server返回給咱們的就是這樣的HTML代碼,僅僅是一般狀況下瀏覽器都會將這些代碼解析成美麗的網頁後再展現出來。

關於http協議的學習,推薦兩個連接:

http://www.cnblogs.com/TankXiao/archive/2012/02/13/2342672.html

http://blog.csdn.net/gueter/article/details/1524447

相關文章
相關標籤/搜索