淺談android訪問http原理

前言

說到HTTP協(xié)議,那必須要說說WWW了,WWW是環(huán)球信息網(World Wide Web )的縮寫,也可以簡稱為Web,中文名字為“萬維網”。簡單來說,WWW是以Internet作為傳輸媒介的一個應用系統(tǒng),WWW網上基本的傳輸單位是Web網頁。WWW的工作是基于B/S模型,由Web瀏覽器和Web服務器構成,兩者之間采用超文本傳輸協(xié)議HTTP協(xié)議進行通信。

HTTP協(xié)議是基于TCP/IP協(xié)議之上的協(xié)議,是Web瀏覽器和Web服務器之間的應用層的協(xié)議,是通用的、無狀態(tài)的面向對象的協(xié)議。關于HTTP協(xié)議的詳細講解,請參見博客:HTTP協(xié)議詳解,里面講解的很清楚,這里主要是說明HTTP在Java中的應用,為從其他技術下轉向Android開發(fā)打好基礎。

首先普及一下網絡協(xié)議的知識,數據在Internet上傳輸,一般通過三種協(xié)議來實現發(fā)送信息和實現:

HTTP協(xié)議,也是在工作中最常用的,是建立在TCP/IP基礎上實現的。

FTP協(xié)議。

TCP/IP協(xié)議,它也是最低層的協(xié)議,其它的方式必須要通過它,但是想要實現這種協(xié)議必須要實現socket編程,這種方法是用來上傳一些比較大的文件,視頻,進行斷電續(xù)傳的操作。

HTTP協(xié)議

下面詳細講解一下HTTP協(xié)議,因為HTTP是無狀態(tài)的協(xié)議,所以服務端并不記錄客戶端之前發(fā)送信息,一碼歸一碼,所以HTTP協(xié)議使用報文頭的形式記錄狀態(tài),一般分為請求報文和響應報文。一般用戶使用瀏覽器訪問網頁,是無需關心HTTP請求的報文頭的,因為開發(fā)人員已經瀏覽器已經幫忙處理了,但是當進行開發(fā)工作的時候,這些是必須要了解的。

對于報文,一般關心請求方式,是GET或者是POST;請求數據類型,是文本還是音頻;數據的編碼格式,一般用utf-8;發(fā)送的數據長度;響應返回碼,一般200為成功,其他響應碼都是有問題。具體了解還是看看上面推薦的博客。

HTTP/1.1協(xié)議中一共定義了八種方法(有時也叫“動作”)來表明Request-URI指定的資源的不同操作方式,但是一般常用的就是GET和POST方式。

這里簡單說一下GET方式和POST方式的差別:

GET是從服務器上獲取數據,POST是向服務器傳送數據。

在客戶端,GET方式在通過URL提交數據,數據在URL中可以看到;POST方式,數據放在HTML HEADER內提交。

對于GET方式,服務器端用Request.QueryString獲取變量的值,對于POST方式,服務器用Request.Form獲取提交的數據。

GET方式提交的數據不能大于2KB(主要是URL長度限制),而POST則沒有此限制。

安全性問題。正如2中提到,使用GET的時候,參數會顯示在地址欄上,而POST不會。所以,如果這些數據是中文數據而且是非敏感數據,那么使用GET;如果用戶輸入的數據不是中文字符而且包含敏感數據,那么還是使用POST為好。

Java中使用HTTP

下面通過兩個例子來分別講解一下GET和POST在Java中的使用,如果在Java中需要使用HTTP協(xié)議進行訪問,一般通過HttpURLConnection類來實現。

HttpURLConnection繼承了URLConnection,所以在URLConnection的基礎上進一步改進,增加了一些用于操作HTTP資源的便捷方法。Java中HttpURLConnection對象通過URL.openConnection()方法來獲得,需要進行強制轉換。先來介紹幾個HttpURLConnection的常用方法:

void?setConnectTimeout(int timeout):設置連接超時時長,如果超過timeout時長,則放棄連接,單位以毫秒計算。

void?setDoInput(boolean newValue) :標志是否允許輸入。

void?setDoOutput(boolean newValue):標志是否允許輸出。

String getRequestMethod():獲取發(fā)送請求的方法。

int getResponseCode():獲取服務器的響應碼。

void setRequestMethod(String method):設置發(fā)送請求的方法。

void setRequestProperty(String field,String newValue):設置請求報文頭,并且只對當前HttpURLConnection有效。

GET方式

這個例子通過GET方式從服務端獲取一張圖片的信息,并把其保存在本地磁盤中。服務器為本機上的IIS,一張靜態(tài)圖片,直接通過URL訪問。

直接上Java代碼,注釋已經解釋的很清楚了。

package com.http.get;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.InputStream;

import java.net.HttpURLConnection;

import java.net.MalformedURLException;

import java.net.URL;

public class HttpUtils {

private static String URL_PATH = "http://192.168.1.106:8080/green.jpg";

/**

* @param args

*/

public static void main(String[] args) {

// 調用方法獲取圖片并保存

saveImageToDisk();

}

/**

* 通過URL_PATH的地址訪問圖片并保存到本地

*/

public static void saveImageToDisk()

{

InputStream inputStream= getInputStream();

byte[] data=new byte[1024];

int len=0;

FileOutputStream fileOutputStream=null;

try {

//把圖片文件保存在本地F盤下

fileOutputStream=new FileOutputStream("F:\\test.png");

while((len=inputStream.read(data))!=-1)

{

//向本地文件中寫入圖片流

fileOutputStream.write(data,0,len);

}

} catch (IOException e) {

e.printStackTrace();

}

finally

{

//最后關閉流

if(inputStream!=null)

{

try {

inputStream.close();

} catch (IOException e) {

e.printStackTrace();

}

}

if(fileOutputStream!=null)

{

try {

fileOutputStream.close();

} catch (IOException e) {

e.printStackTrace();

}

}

}

}

/**

* 通過URL獲取圖片

* @return URL地址圖片的輸入流。

*/

public static InputStream getInputStream() {

InputStream inputStream = null;

HttpURLConnection httpURLConnection = null;

try {

//根據URL地址實例化一個URL對象,用于創(chuàng)建HttpURLConnection對象。

URL url = new URL(URL_PATH);

if (url != null) {

//openConnection獲得當前URL的連接

httpURLConnection = (HttpURLConnection) url.openConnection();

//設置3秒的響應超時

httpURLConnection.setConnectTimeout(3000);

//設置允許輸入

httpURLConnection.setDoInput(true);

//設置為GET方式請求數據

httpURLConnection.setRequestMethod("GET");

//獲取連接響應碼,200為成功,如果為其他,均表示有問題

int responseCode=httpURLConnection.getResponseCode();

if(responseCode==200)

{

//getInputStream獲取服務端返回的數據流。

inputStream=httpURLConnection.getInputStream();

}

}

} catch (MalformedURLException e) {

e.printStackTrace();

} catch (IOException e) {

e.printStackTrace();

}

return inputStream;

}

}

POST方式

這個例子通過POST方式訪問一個登陸頁面,需要輸入用戶名(username)和密碼(password)。雖然這里使用的Java在講解問題,但是服務端是使用.Net的框架,一個很簡單的HTML頁面加一個表單傳送的一般處理程序,輸入為admin+123為登陸成功,這里不累述了。

package com.http.post;import java.io.ByteArrayOutputStream;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.io.UnsupportedEncodingException;import java.net.HttpURLConnection;import java.net.URL;import java.net.URLEncoder;import java.util.HashMap;import java.util.Map;public class postUtils {? ? private static String PATH = "http://192.168.222.1:1231/loginas.ashx";? ? private static URL url;? ? public postUtils() {? ? }? ? static {? ? ? ? try {? ? ? ? ? ? url = new URL(PATH);? ? ? ? } catch (Exception e) {? ? ? ? ? ? e.printStackTrace();? ? ? ? }? ? }? ? ? ? /**? ? * 通過給定的請求參數和編碼格式,獲取服務器返回的數據? ? * @param params 請求參數? ? * @param encode 編碼格式? ? * @return 獲得的字符串? ? */? ? public static String sendPostMessage(Mapparams,? ? ? ? ? ? String encode) {? ? ? ? StringBuffer buffer = new StringBuffer();? ? ? ? if (params != null && !params.isEmpty()) {? ? ? ? ? ? for (Map.Entryentry : params.entrySet()) {? ? ? ? ? ? ? ? try {? ? ? ? ? ? ? ? ? ? buffer.append(entry.getKey())? ? ? ? ? ? ? ? ? ? ? ? ? ? .append("=")? ? ? ? ? ? ? ? ? ? ? ? ? ? .append(URLEncoder.encode(entry.getValue(), encode))? ? ? ? ? ? ? ? ? ? ? ? ? ? .append("&");//請求的參數之間使用&分割。? ? ? ? ? ? ? ? } catch (UnsupportedEncodingException e) {? ? ? ? ? ? ? ? ? ? e.printStackTrace();? ? ? ? ? ? ? ? }? ? ? ? ? ? }? ? ? ? ? ? buffer.deleteCharAt(buffer.length() - 1);? ? ? ? ? ? System.out.println(buffer.toString());? ? ? ? ? ? try {? ? ? ? ? ? ? ? HttpURLConnection urlConnection = (HttpURLConnection) url? ? ? ? ? ? ? ? ? ? ? ? .openConnection();? ? ? ? ? ? ? ? urlConnection.setConnectTimeout(3000);? ? ? ? ? ? ? ? //設置允許輸入輸出? ? ? ? ? ? ? ? urlConnection.setDoInput(true);? ? ? ? ? ? ? ? urlConnection.setDoOutput(true);? ? ? ? ? ? ? ? byte[] mydata = buffer.toString().getBytes();? ? ? ? ? ? ? ? //設置請求報文頭,設定請求數據類型? ? ? ? ? ? ? ? urlConnection.setRequestProperty("Content-Type",? ? ? ? ? ? ? ? ? ? ? ? "application/x-www-form-urlencoded");? ? ? ? ? ? ? ? //設置請求數據長度? ? ? ? ? ? ? ? urlConnection.setRequestProperty("Content-Length",? ? ? ? ? ? ? ? ? ? ? ? String.valueOf(mydata.length));? ? ? ? ? ? ? ? //設置POST方式請求數據? ? ? ? ? ? ? ? urlConnection.setRequestMethod("POST");? ? ? ? ? ? ? ? OutputStream outputStream = urlConnection.getOutputStream();? ? ? ? ? ? ? ? outputStream.write(mydata);? ? ? ? ? ? ? ? int responseCode = urlConnection.getResponseCode();? ? ? ? ? ? ? ? if (responseCode == 200) {? ? ? ? ? ? ? ? ? ? return changeInputStream(urlConnection.getInputStream(),? ? ? ? ? ? ? ? ? ? ? ? ? ? encode);? ? ? ? ? ? ? ? }? ? ? ? ? ? } catch (IOException e) {? ? ? ? ? ? ? ? e.printStackTrace();? ? ? ? ? ? }? ? ? ? }? ? ? ? return "";? ? }? ? /**? ? * 把服務端返回的輸入流轉換成字符串格式? ? * @param inputStream 服務器返回的輸入流? ? * @param encode 編碼格式? ? * @return 解析后的字符串? ? */? ? private static String changeInputStream(InputStream inputStream,? ? ? ? ? ? String encode) {? ? ? ? ByteArrayOutputStream outputStream = new ByteArrayOutputStream();? ? ? ? byte[] data = new byte[1024];? ? ? ? int len = 0;? ? ? ? String result="";? ? ? ? if (inputStream != null) {? ? ? ? ? ? try {? ? ? ? ? ? ? ? while ((len = inputStream.read(data)) != -1) {? ? ? ? ? ? ? ? ? ? outputStream.write(data,0,len);? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? result=new String(outputStream.toByteArray(),encode);? ? ? ? ? ? ? ? ? ? ? ? ? ? } catch (IOException e) {? ? ? ? ? ? ? ? e.printStackTrace();? ? ? ? ? ? }? ? ? ? }? ? ? ? return result;? ? }? ? /**? ? * @param args? ? */? ? public static void main(String[] args) {? ? ? ? //通過Map設置請求字符串。? ? ? ? Mapparams = new HashMap();

params.put("username", "admin");

params.put("password", "123");

String result=sendPostMessage(params, "utf-8");

System.out.println(result);

}

}

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容