Android中的HTTP通信筆記(慕課網)

Android中的HTTP通信筆記(慕課網)

本文是基於慕課網nate老師講解Android中Http通信,自己做的整理筆記,在此感謝nate老師和慕課網的分享,視頻鏈接如下http://www.imooc.com/learn/304


HTTP協議

HTTP協議是超文本傳輸協議定義了瀏覽器怎麼向萬維網請求萬維網文檔,及服務器怎麼把文檔傳送給瀏覽器。從層次的角度看,HTTP協議是面向應用層的協議。

HTTP協議特點

HTTP協議特點包括以下幾個方面:

  • 支持客戶機服務器模式

  • 簡單快速:客戶機向服務器請求服務時,只需要傳送請求方法和路徑。請求的方法包括GET、HEAD、POST等。每種方法規定了客戶與服務器聯繫的類型不同。由於HTTP協議簡單,使得HTTP服務器的規模小,通信速度快。

  • 靈活:HTTP運行傳輸任何類型的數據對象。

  • 無連接:限制每次連接只處理一個請求。服務器處理完用戶的請求,並收到客戶的應答後,即斷開連接。採用這種方式可以節省傳輸時間。

  • 無狀態:HTTP協議是無狀態協議。無狀態是指協議對於事務的處理沒有記憶的能力。缺少狀態意味着如果後續處理需要前面的信息,則必須重傳,這樣可能導致每次連接傳送的數據量增大。另一方面,在服務器不需要先前信息時它的應答就較快。


一個HTTP協議操作成爲一個事務,其工作過程可以分爲四步:

  1. 首先客戶機和服務器之間建立相應的連接,只要單擊某個超鏈接,HTTP就可以工作。

  2. 建立連接之後,客戶機發送一個請求給服務器,請求方式的格式爲:統一資源標識符(URL)、協議版本號,後邊的MIME信息包括請求標識符、客戶機信息和可能的內容。

  3. 服務器接收到請求後 ,給予相應的相應信息。其格式爲一個狀態行,包括信息的協議版本號、一個成功或錯誤的代碼,後邊是MIME信息包括服務器信息、實體信息和可能的內容。

  4. 客戶端接收服務器所返回的信息通過瀏覽器顯示在用戶的現實屏上,然後客戶機與服務器斷開連接。


統一資源定位符(URL)

統一資源定位符(URL)也被稱爲網頁地址。

URL的格式由三部分組成:

第一部分是協議;

第二部分是存有該資源的主機IP地址(有時也包括端口號);

第三部分是主機資源的具體地址。

eg.http//www.imooc.com/index.jsp

TCP三次握手

SYN是TCP/IP建立連接時使用的握手信號。客戶機和服務器之間建立連接,首先客戶機發出一個SYN信號,服務器使用SYN+ACK應答表示接收到了這個消息,最後客戶機再以ACK消息響應。

ACK即確認符,在數據通信中,接收站給發送站的一種傳輸類控制字符,表示發來的數據已確認接收無誤。

HTTP請求

Http請求由三部分組成,分別是:請求行、消息報頭、請求正文。

請求行以一個方法符號開頭,以空格分開,後面跟着請求的URI和協議的版本號,格式如下:Method Request-URI HTTP-Version CRLF

其中Method表示請求的方法;Request-URI是一個統一資源標識符;HTTP-Version標識請求的HTTP協議版本;CRLF表示回車和換行(除了作爲結尾的CRLF之外,不允許出現單獨的CR或LF字符)。

請求方法(所有方法全爲大寫)有多種,各個方法解釋如下:

GET 請求獲取Request-URI所標識的資源

POST 在Request-URI所標識的資源後附加新的數據

HEAD 請求獲取由Request-URI所標識的資源的響應消息報頭

PUT 請求服務器存儲一個資源,並用Request-URI作爲其標識

DELETE 請求服務器刪除Request-URI所標識的資源

TRACE 請求服務器回送收到的請求信息,主要用於測試或診斷

CONNECT 保留將來使用

OPTIONS 請求查詢服務器的性能,或者查詢與資源相關的選項和需求

應用舉例:

GET方法:在瀏覽器的地址欄輸入網址的方式訪問網頁時,瀏覽器採用GET方法向服務器獲取資源,eg:GET/form.html HTTP/1.1(CRLF)

POST方法:要求被請求服務器接受負載請求後面的數據,常用於提交表單。

HTTP響應

在接收和解釋請求消息後,服務器返回一個HTTP響應消息。

HTTP響應也是由三個部分組成,分別是:狀態行、消息報頭、響應正文。

狀態行格式如下:

HTTP-Version Status——Code Reason-Phrase CRLF

其中,HTTP-Version標識服務器HTTP協議的版本;Status-Code標識服務器發回的響應狀態代碼;Reason-Phrase表示狀態代碼的文本描述。

狀態代碼有三位數字組成,第一個數字定義了響應的類別,且有五種可能取值:
1xx:指示信息–表示請求已接收,繼續處理
2xx:成功–表示請求已被成功接收、理解、接受
3xx:重定向–要完成請求必須進行更進一步的操作
4xx:客戶端錯誤–請求有語法錯誤或請求無法實現
5xx:服務器端錯誤–服務器未能實現合法的請求

常見狀態代碼、狀態描述、說明:
200 OK //客戶端請求成功
400 Bad Request //客戶端請求有語法錯誤,不能被服務器所理解
401 Unauthorized //請求未經授權,這個狀態代碼必須和WWW-Authenticate報頭域一起使用
403 Forbidden //服務器收到請求,但是拒絕提供服務
404 Not Found //請求資源不存在,eg:輸入了錯誤的URL
500 Internal Server Error //服務器發生不可預期的錯誤
503 Server Unavailable //服務器當前不能處理客戶端的請求,一段時間後可能恢復正常
eg:HTTP/1.1 200 OK (CRLF)

HTTP1.0和HTTP1.1區別

HTTP/1.0 每次請求都需要建立新的TCP連接,連接不可複用。
HTTP/1.1 新的請求可以在上次請求建立的TCP連接之上發送,連接可以複用,優點是減少重複進行TCP三次握手的開銷,提高效率。
HTTP/1.1 在Request消息頭裏多了一個HOST域,HTTP1.0則沒有這個域。HOST:www.w3.org
HTTP1.1 增加了OPTIONS,PUT,DELETE,TRACE,CONNECT這些Request方法。

HttpURLConnection

在Android中發送HTTP請求的方式一般有兩種,HttpURLConnection和HttpClient(Android 5.0中已棄用)在這裏我們只介紹HttpURLConnection.

從網上下載圖片保存到SD中

  1. 代碼

HttpThread.java

package com.excavator.http_01;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Environment;
import android.os.Handler;
import android.webkit.WebView;
import android.widget.ImageView;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;


/**
 * Created by admin on 2015/4/16.
 */
public class HttpThread extends Thread {
    private String url;

    private WebView webView;

    private Handler handler;

    private ImageView imageView;

    public HttpThread(String url, WebView webView, Handler handler) {
        this.url = url;
        this.webView = webView;
        this.handler = handler;
    }

    public HttpThread(String url, ImageView imageView,Handler handler) {
        this.url = url;
        this.handler = handler;
        this.imageView = imageView;
    }

    @Override
    public void run() {
        try {
            URL httpUrl = new URL(url);
            try {
                //從Url建立Http連接
                HttpURLConnection connection = (HttpURLConnection) httpUrl.openConnection();
                connection.setReadTimeout(5000);
                connection.setRequestMethod("GET");
                connection.setDoInput(true);
                //從Http連接獲取輸入流
                InputStream in = connection.getInputStream();
                FileOutputStream outputStream=null;
                File downloadFile=null;
                String fileName = String.valueOf(System.currentTimeMillis());
                //判斷外部SD卡是否存在
                if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
                    File parent = Environment.getExternalStorageDirectory();    //獲取SD卡根目錄
                    downloadFile=new File(parent,fileName);                     //在SD卡根目錄下新建downloadFile
                    outputStream0.000000000000000000 = new FileOutputStream(downloadFile);          //構建寫字節到downloadFile的輸出流
                }
                //建立緩衝數組
                byte[] b = new byte[2*1024];
                int len;
                if (outputStream!=null){
                    while ((len=in.read(b))!=-1){   //讀輸入流中的字符緩衝到字節數組b中
                        outputStream.write(b,0,len);//寫字節數組b中的字符到輸出流中(即到文件downloadFile中)
                    }
                }
                //解碼文件路徑爲位圖bitmap
                final Bitmap bitmap = BitmapFactory.decodeFile(downloadFile.getAbsolutePath());
                handler.post(new Runnable() {
                    @Override
                    public void run() {
                        imageView.setImageBitmap(bitmap);
                    }
                });
                /*final StringBuffer stringBuffer = new StringBuffer();
                BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
                String str;
                while ((str=reader.readLine())!=null) {
                    stringBuffer.append(str);
                }


                handler.post(new Runnable() {
                    @Override
                    public void run() {
                        webView.loadData(stringBuffer.toString(), "text/html;charset=utf-8", null);
                    }
                });*/
            } catch (IOException e) {
                e.printStackTrace();
            }
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }
    }
}

MainActivity.java

package com.excavator.http_01;

import android.os.Bundle;
import android.os.Handler;
import android.support.v7.app.ActionBarActivity;
import android.webkit.WebView;
import android.widget.ImageView;


public class MainActivity extends ActionBarActivity {

    private WebView webView;

    private Handler handler=new Handler();

    private ImageView imageView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //webView = (WebView) findViewById(R.id.webView);
        imageView = (ImageView) findViewById(R.id.imageView);
        new HttpThread("http://h.hiphotos.baidu.com/image/pic/item/6c224f4a20a446239e8d311c9b22720e0cf3d70d.jpg",imageView,handler).start();
    }
}

GET、POST傳遞參數

主機服務器代碼
MyServlet.java

package com.imooc.servlet;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Servlet implementation class MyServlet
 */
@WebServlet("/MyServlet")
public class MyServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;

    /**
     * @see HttpServlet#HttpServlet()
     */
    public MyServlet() {
        super();
        // TODO Auto-generated constructor stub
    }

    /**
     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        this.doPost(request, response);
    }

    /**
     * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        String name=request.getParameter("name");
        String age=request.getParameter("age");
        response.setContentType("text/html;charset=utf-8");
        PrintWriter out=response.getWriter();
        //out.println("name="+new String(name.getBytes("iso-8859-1"),"utf-8")+"age="+age);
        out.println("name="+name+"age="+age);
        //System.out.println("name="+new String(name.getBytes("iso-8859-1"),"utf-8"));
        System.out.println("name="+name);
        System.out.println("age="+age);
    }

}

HttpThread1(從Android端向服務器端提交數據)

package com.excavator.http_01;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.Properties;

/**
 * Created by admin on 2015/4/17.
 */
public class HttpThread1 extends Thread {

    String url;

    String name;

    String age;

    public HttpThread1(String url, String name, String age) {
        this.url = url;
        this.name = name;
        this.age = age;
    }

    private  void doGet() {
        try {
            url = url + "?name=" + URLEncoder.encode(name,"utf-8") + "&age=" + age; //此處URLEncoder中的encode方法用於轉碼,因爲Android中編碼是utf-8碼,若不轉碼,服務器端接收到中文會是亂碼。
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        try {
            URL httpUrl = new URL(url);
            try {
                HttpURLConnection httpURLConnection = (HttpURLConnection) httpUrl.openConnection();
                httpURLConnection.setRequestMethod("GET");
                httpURLConnection.setReadTimeout(5000);
                BufferedReader reader = new BufferedReader(new InputStreamReader(httpURLConnection.getInputStream()));
                String str;
                StringBuffer stringBuffer = new StringBuffer();
                while ((str = reader.readLine()) != null) {
                    stringBuffer.append(str);
                }
                System.out.println("result" + stringBuffer.toString());
            } catch (IOException e) {
                e.printStackTrace();
            }
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }
    }

    private void doPost() {
        try {
            Properties properties = System.getProperties();
            properties.list(System.out);


            URL httpUrl = new URL(url);
            try {
                HttpURLConnection httpURLConnection = (HttpURLConnection) httpUrl.openConnection();
                httpURLConnection.setRequestMethod("POST");
                httpURLConnection.setReadTimeout(5000);
                OutputStream out = httpURLConnection.getOutputStream();
                String content = "name=" + name + "&age=" + age;
                out.write(content.getBytes());
                BufferedReader reader = new BufferedReader(new InputStreamReader(httpURLConnection.getInputStream()));
                StringBuffer sb = new StringBuffer();
                String str;

                while ((str = reader.readLine()) != null) {
                    sb.append(str);
                }
                System.out.println(sb.toString());

            } catch (IOException e) {
                e.printStackTrace();
            }
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void run() {
        super.run();
        doGet();
//        doPost();
    }

}

這裏寫圖片描述
這裏寫圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章