淺談android訪問http原理

前言

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

HTTP協(xié)議是基于TCP/IP協(xié)議之上的協(xié)議,是Web瀏覽器和Web服務(wù)器之間的應(yīng)用層的協(xié)議,是通用的、無(wú)狀態(tài)的面向?qū)ο蟮膮f(xié)議。關(guān)于HTTP協(xié)議的詳細(xì)講解,請(qǐng)參見博客:HTTP協(xié)議詳解,里面講解的很清楚,這里主要是說(shuō)明HTTP在Java中的應(yīng)用,為從其他技術(shù)下轉(zhuǎn)向Android開發(fā)打好基礎(chǔ)。

首先普及一下網(wǎng)絡(luò)協(xié)議的知識(shí),數(shù)據(jù)在Internet上傳輸,一般通過三種協(xié)議來(lái)實(shí)現(xiàn)發(fā)送信息和實(shí)現(xiàn):

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

FTP協(xié)議。

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

HTTP協(xié)議

下面詳細(xì)講解一下HTTP協(xié)議,因?yàn)镠TTP是無(wú)狀態(tài)的協(xié)議,所以服務(wù)端并不記錄客戶端之前發(fā)送信息,一碼歸一碼,所以HTTP協(xié)議使用報(bào)文頭的形式記錄狀態(tài),一般分為請(qǐng)求報(bào)文和響應(yīng)報(bào)文。一般用戶使用瀏覽器訪問網(wǎng)頁(yè),是無(wú)需關(guān)心HTTP請(qǐng)求的報(bào)文頭的,因?yàn)殚_發(fā)人員已經(jīng)瀏覽器已經(jīng)幫忙處理了,但是當(dāng)進(jìn)行開發(fā)工作的時(shí)候,這些是必須要了解的。

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

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

這里簡(jiǎn)單說(shuō)一下GET方式和POST方式的差別:

GET是從服務(wù)器上獲取數(shù)據(jù),POST是向服務(wù)器傳送數(shù)據(jù)。

在客戶端,GET方式在通過URL提交數(shù)據(jù),數(shù)據(jù)在URL中可以看到;POST方式,數(shù)據(jù)放在HTML HEADER內(nèi)提交。

對(duì)于GET方式,服務(wù)器端用Request.QueryString獲取變量的值,對(duì)于POST方式,服務(wù)器用Request.Form獲取提交的數(shù)據(jù)。

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

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

Java中使用HTTP

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

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

void?setConnectTimeout(int timeout):設(shè)置連接超時(shí)時(shí)長(zhǎng),如果超過timeout時(shí)長(zhǎng),則放棄連接,單位以毫秒計(jì)算。

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

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

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

int getResponseCode():獲取服務(wù)器的響應(yīng)碼。

void setRequestMethod(String method):設(shè)置發(fā)送請(qǐng)求的方法。

void setRequestProperty(String field,String newValue):設(shè)置請(qǐng)求報(bào)文頭,并且只對(duì)當(dāng)前HttpURLConnection有效。

GET方式

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

直接上Java代碼,注釋已經(jīng)解釋的很清楚了。

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) {

// 調(diào)用方法獲取圖片并保存

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

{

//最后關(guān)閉流

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 {

//根據(jù)URL地址實(shí)例化一個(gè)URL對(duì)象,用于創(chuàng)建HttpURLConnection對(duì)象。

URL url = new URL(URL_PATH);

if (url != null) {

//openConnection獲得當(dāng)前URL的連接

httpURLConnection = (HttpURLConnection) url.openConnection();

//設(shè)置3秒的響應(yīng)超時(shí)

httpURLConnection.setConnectTimeout(3000);

//設(shè)置允許輸入

httpURLConnection.setDoInput(true);

//設(shè)置為GET方式請(qǐng)求數(shù)據(jù)

httpURLConnection.setRequestMethod("GET");

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

int responseCode=httpURLConnection.getResponseCode();

if(responseCode==200)

{

//getInputStream獲取服務(wù)端返回的數(shù)據(jù)流。

inputStream=httpURLConnection.getInputStream();

}

}

} catch (MalformedURLException e) {

e.printStackTrace();

} catch (IOException e) {

e.printStackTrace();

}

return inputStream;

}

}

POST方式

這個(gè)例子通過POST方式訪問一個(gè)登陸頁(yè)面,需要輸入用戶名(username)和密碼(password)。雖然這里使用的Java在講解問題,但是服務(wù)端是使用.Net的框架,一個(gè)很簡(jiǎn)單的HTML頁(yè)面加一個(gè)表單傳送的一般處理程序,輸入為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();? ? ? ? }? ? }? ? ? ? /**? ? * 通過給定的請(qǐng)求參數(shù)和編碼格式,獲取服務(wù)器返回的數(shù)據(jù)? ? * @param params 請(qǐng)求參數(shù)? ? * @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("&");//請(qǐng)求的參數(shù)之間使用&分割。? ? ? ? ? ? ? ? } catch (UnsupportedEncodingException e) {? ? ? ? ? ? ? ? ? ? e.printStackTrace();? ? ? ? ? ? ? ? }? ? ? ? ? ? }? ? ? ? ? ? buffer.deleteCharAt(buffer.length() - 1);? ? ? ? ? ? System.out.println(buffer.toString());? ? ? ? ? ? try {? ? ? ? ? ? ? ? HttpURLConnection urlConnection = (HttpURLConnection) url? ? ? ? ? ? ? ? ? ? ? ? .openConnection();? ? ? ? ? ? ? ? urlConnection.setConnectTimeout(3000);? ? ? ? ? ? ? ? //設(shè)置允許輸入輸出? ? ? ? ? ? ? ? urlConnection.setDoInput(true);? ? ? ? ? ? ? ? urlConnection.setDoOutput(true);? ? ? ? ? ? ? ? byte[] mydata = buffer.toString().getBytes();? ? ? ? ? ? ? ? //設(shè)置請(qǐng)求報(bào)文頭,設(shè)定請(qǐng)求數(shù)據(jù)類型? ? ? ? ? ? ? ? urlConnection.setRequestProperty("Content-Type",? ? ? ? ? ? ? ? ? ? ? ? "application/x-www-form-urlencoded");? ? ? ? ? ? ? ? //設(shè)置請(qǐng)求數(shù)據(jù)長(zhǎng)度? ? ? ? ? ? ? ? urlConnection.setRequestProperty("Content-Length",? ? ? ? ? ? ? ? ? ? ? ? String.valueOf(mydata.length));? ? ? ? ? ? ? ? //設(shè)置POST方式請(qǐng)求數(shù)據(jù)? ? ? ? ? ? ? ? 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 "";? ? }? ? /**? ? * 把服務(wù)端返回的輸入流轉(zhuǎn)換成字符串格式? ? * @param inputStream 服務(wù)器返回的輸入流? ? * @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設(shè)置請(qǐng)求字符串。? ? ? ? Mapparams = new HashMap();

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

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

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

System.out.println(result);

}

}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容