1. 程式人生 > >HTTP傳輸協議詳解(簡單易懂)

HTTP傳輸協議詳解(簡單易懂)

前言
HTTP: HyperText Transfer Protocol超文字傳輸協議,是網際網路上應用最為廣泛的一種網路協議,所有的WWW檔案都必須遵守這個標準;屬於應用層的面向物件的協議,由於其簡捷、快速的方式,適用於分散式超媒體資訊系統。它於1990年提出,經過幾年的使用與發展,得到不斷地完善和擴充套件。
一、主要特點:
1.支援客戶/伺服器模式。
2.簡單快速:客戶向伺服器請求服務時,只需傳送請求方法和路徑。請求方法常用的有GET、HEAD、POST。每種方法規定了客戶與伺服器聯絡的型別不同。由於HTTP協議簡單,使得HTTP伺服器的程式規模小,因而通訊速度很快。
3.靈活:HTTP允許傳輸任意型別的資料物件。正在傳輸的型別由Content-Type加以標記。
4.無連線:無連線的含義是限制每次連線只處理一個請求。伺服器處理完客戶的請求,並收到客戶的應答後,即斷開連線。採用這種方式可以節省傳輸時間。
5.無狀態:HTTP協議是無狀態協議。無狀態是指協議對於事務處理沒有記憶能力。缺少狀態意味著如果後續處理需要前面的資訊,則它必須重傳,這樣可能導致每次連線傳送的資料量增大。另一方面,在伺服器不需要先前資訊時它的應答就較快。
二、主要功能詳解:


1.HTTP訪問入口:通過特殊的URL來定位網路資源
格式:http://host[:port][abs_path]
其中:
http:表示要通過HTTP協議來定位網路資源。
  host:表示合法的Internet主機域名或IP地址(以點分十進位制格式表示);
  port:用於指定一個埠號,擁有被請求資源的伺服器主機監聽該埠的TCP連線。
   如果port是空,則使用預設的埠80。當伺服器的埠不是80的時候,需要顯式指定埠號。
  abs_path:指定請求資源的URI(Uniform Resource Identifier,統一資源定位符),如果URL中沒有給出
abs_path,那麼當它作為請求URI時,必須以“/”的形式給出。通常這個工作瀏覽器就幫我們完
成了。

2.HTTP的請求方式
http請求由三部分組成,分別是:請求行、訊息報頭、請求正文
主要包含有八中請求方式:
(1)OPTIONS 返回伺服器針對特定資源所支援的HTML請求方法 或web伺服器傳送測試伺服器功能(允許
客戶端檢視伺服器效能)
(2)GET 向特定資源發出請求(請求指定頁面資訊,並返回實體主體)
(3)POST 向指定資源提交資料進行處理請求(提交表單、上傳檔案),又可能導致新的資源的建立或原有
資源的修改
(4)PUT 向指定資源位置上上傳其最新內容(從客戶端向伺服器傳送的資料取代指定文件的內容)
(5)HEAD 與伺服器索與get請求一致的相應,響應體不會返回,獲取包含在小訊息頭中的原資訊(與get請求
類似,返回的響應中沒有具體內容,用於獲取報頭)
(6)DELECT 請求伺服器刪除request-URL所標示的資源

(請求伺服器刪除頁面)
(7)TRACE 回顯伺服器收到的請求,用於測試和診斷
(8)CONNECT HTTP/1.1協議中能夠將連線改為管道方式的代理伺服器
一般最常用的是GET、POST方法的請求。

最常用的案例:
(1)請求post方式:
注意一下:在客戶端請求訪問服務後臺使用的時候,客戶端提交的資料必須放在訊息主體中(entity-body),協議的資料 編碼方式可以由開發者自行設定;在服務端通常是根據請求頭(headers)中的Content-Type欄位來獲取請求中的訊息主體使用的方式編碼,然後再根據其編碼方式進行解析訊息主體。

public  String getHttpResponse(String url,String param){
	
/*	DefaultHttpClient client = new DefaultHttpClient();
    HttpPost post = new HttpPost(url);
   JSONObject response = null;
    try {
        StringEntity s = new StringEntity(json.toString());
        s.setContentEncoding("UTF-8");
       s.setContentType("application/json");
        post.setEntity(s);
        HttpResponse res = client.execute(post);
        if(res.getStatusLine().getStatusCode() == HttpStatus.SC_OK){
            HttpEntity entity = res.getEntity();
            String result = EntityUtils.toString(res.getEntity());
           response = JSONObject.fromObject(result);
        }
   } catch (Exception e) {
       throw new RuntimeException(e);
    }
    return response.toString();
}*/
	try {	
		//請求http請求連線
		URL postUrl=new URL(url);
		HttpURLConnection httpurlConn = (HttpURLConnection) postUrl.openConnection() ;
		httpurlConn.setRequestMethod("POST");
		httpurlConn.setRequestProperty("Content-Type", "application/json;charset=UTF-8");
		httpurlConn.setRequestProperty("Connection", "Keep-Alive");
		httpurlConn.setRequestProperty("Content-Length", "0");
		httpurlConn.setDoInput(true);//是否輸出引數
		httpurlConn.setDoOutput(true);//是否輸入引數
		DataOutputStream dosDataOutputStream=new DataOutputStream(httpurlConn.getOutputStream());
		dosDataOutputStream.write(param.getBytes("UTF-8"));
		dosDataOutputStream.flush();
		dosDataOutputStream.close();
		httpurlConn.connect();//開始連線
		//獲取連線response響應
		if(httpurlConn.getResponseCode()==200){//獲取響應狀態碼,有響應
			System.out.println("響應成功!");
			InputStream inputStream=httpurlConn.getInputStream();
			InputStreamReader isReader=new InputStreamReader(inputStream,"utf-8");
			BufferedReader br=new BufferedReader(isReader);
			String str="";
			Map map;
			while((str=br.readLine())!=null){
				map=(Map)JSONObject.fromObject(str);
				System.out.println(map.toString());
			}
		}
	} catch (IOException e) {
		e.printStackTrace();
	}finally{
           try {         //最後記得關閉所有的IO流
			br.close();
			isReader.close();
			inputStream.close();
			httpurlConn.disconnect();
		} catch (IOException e) {
                     e.printStackTrace();
                     }
           }
	return null;
}

(2)或者:

public String Callservce(String strURL, String param,
			String method, String contentType) {
		try {
			// 建立url資源
			URL url = new URL(strURL);
			// 建立http連線
			HttpURLConnection conn = (HttpURLConnection) url.openConnection();
			conn.setConnectTimeout(120000);
			conn.setReadTimeout(24*60*60*1000);
			// 設定允許輸出
			conn.setDoOutput(true);
			conn.setDoInput(true);
			// 設定不用快取
			conn.setUseCaches(false);
			// 設定傳遞方式
			conn.setRequestMethod(method);
			// 設定維持長連線
			conn.setRequestProperty("Connection", "Keep-Alive");
			// 設定檔案字符集:
			conn.setRequestProperty("Charset", "UTF-8");
			// 轉換為位元組陣列
			byte[] data = param.getBytes("UTF-8");
			// 設定檔案長度
			conn.setRequestProperty("Content-Length",
					String.valueOf(data.length));
			// 設定檔案型別:
			conn.setRequestProperty("content-Type", contentType);
			// 開始連線請求
			conn.connect();
			OutputStream out = conn.getOutputStream();
			// 寫入請求的字串
			out.write(data);
			out.flush();
			out.close();
			// 請求返回的狀態
			if (conn.getResponseCode() == 200) {
				// 請求返回的資料
				InputStream in = conn.getInputStream();
				int size = conn.getContentLength();
				return readString(in, size, "utf-8");
			} else {
				return Integer.toString(conn.getResponseCode());
			}
		} catch (Exception e) {
			return e.getMessage();
		}
	}

3.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 //伺服器當前不能處理客戶端的請求,一段時間後可能恢復正常
4.HTTP的訊息報頭
HTTP訊息報頭包括普通報頭、請求報頭、響應報頭、實體報頭。
HTTP訊息由客戶端到伺服器的請求和伺服器到客戶端的響應組成。請求訊息和響應訊息都是由開始行(對於請求訊息,開始行就是請求行,對於響應訊息,開始行就是狀態行),訊息報頭(可選),空行(只有CRLF的行),訊息正文(可選)組成。每一個報頭域都是由名字+“:”+空格+值 組成,訊息報頭域的名字是大小寫無關的。例如:

GET /form.html HTTP/1.1 (CRLF)
Accept:image/gif,image/x-xbitmap,image/jpeg,application/x-shockwave-flash,application/vnd.ms-excel,application/vnd.ms-powerpoint,application/msword,/
(CRLF) Accept-Language:zh-cn (CRLF) Accept-Encoding:gzip,deflate
(CRLF) If-Modified-Since:Wed,05 Jan 2007 11:21:25 GMT (CRLF)
If-None-Match:W/“80b1a4c018f3c41:8317” (CRLF)
User-Agent:Mozilla/4.0(compatible;MSIE6.0;Windows NT 5.0) (CRLF)
Host:www.guet.edu.cn (CRLF) Connection:Keep-Alive (CRLF) (CRLF)

(1)普通報頭
在普通報頭中,有少數報頭域用於所有的請求和響應訊息,但並不用於被傳輸的實體,只用於傳輸的訊息。
例如:普通報頭域:Cache-Control:no-cache
Cache-Control 用於指定快取指令,快取指令是單向的(響應中出現的快取指令在請求中未必會出現),且是獨立的(一個訊息的快取指令不會影響另一個訊息處理的快取機制),HTTP1.0使用的類似的報頭域為Pragma。
no-cache(用於指示請求或響應訊息不能快取)。
(2)請求報頭
請求報頭允許客戶端向伺服器端傳遞請求的附加資訊以及客戶端自身的資訊。
常用請求報頭:
Accept:請求報頭域用於指定客戶端接受哪些型別的資訊。eg:Accept:image/gif,表明客戶端希望接受GIF圖象格式的資源;Accept:text/html,表明客戶端希望接受html文字。
Accept-Charset:請求報頭域用於指定客戶端接受的字符集。eg:Accept-Charset:iso-8859-1,gb2312.如果在請求訊息中沒有設定這個域,預設是任何字符集都可以接受。
Accept-Charset:請求報頭域用於指定客戶端接受的字符集。eg:Accept-Charset:iso-8859-1,gb2312.如果在請求訊息中沒有設定這個域,預設是任何字符集都可以接受。
Accept-Language:請求報頭域類似於Accept,但是它是用於指定一種自然語言。eg:Accept-Language:zh-cn.如果請求訊息中沒有設定這個報頭域,伺服器假定客戶端對各種語言都可以接受。
Authorization:請求報頭域主要用於證明客戶端有權檢視某個資源。當瀏覽器訪問一個頁面時,如果收到伺服器的響應程式碼為401(未授權),可以傳送一個包含Authorization請求報頭域的請求,要求伺服器對其進行驗證。
Host:請求報頭域主要用於指定被請求資源的Internet主機和埠號,它通常從HTTP URL中提取出來的
User-Agent :我們上網登陸論壇的時候,往往會看到一些歡迎資訊,其中列出了你的作業系統的名稱和版本,你所使用的瀏覽器的名稱和版本,這往往讓很多人感到很神奇,實際上,伺服器應用程式就是從User-Agent這個請求報頭域中獲取到這些資訊。User-Agent請求報頭域允許客戶端將它的作業系統、瀏覽器和其它屬性告訴伺服器。不過,這個報頭域不是必需的,如果我們自己編寫一個瀏覽器,不使用User-Agent請求報頭域,那麼伺服器端就無法得知我們的資訊了。
(3)響應報頭
響應報頭允許伺服器傳遞不能放在狀態行中的附加響應資訊,以及關於伺服器的資訊和對Request-URI所標識的資源進行下一步訪問的資訊.
常用的響應報頭:
Location:響應報頭域用於重定向接受者到一個新的位置。Location響應報頭域常用在更換域名的時候。
Server:響應報頭域包含了伺服器用來處理請求的軟體資訊。與User-Agent請求報頭域是相對應的。
WWW-Authenticate:響應報頭域必須被包含在401(未授權的)響應訊息中,客戶端收到401響應訊息時候,併發送Authorization報頭域請求伺服器對其進行驗證時,服務端響應報頭就包含該報頭域。
(4)實體報頭
請求和響應訊息都可以傳送一個實體。一個實體由實體報頭域和實體正文組成,但並不是說實體報頭域和實體正文要在一起傳送,可以只發送實體報頭域。實體報頭定義了關於實體正文(eg:有無實體正文)和請求所標識的資源的元資訊。
常用實體報頭:
Content-Encoding:實體報頭域被用作媒體型別的修飾符,它的值指示了已經被應用到實體正文的附加內容的編碼,因而要獲得Content-Type報頭域中所引用的媒體型別,必須採用相應的解碼機制。
Content-Language:實體報頭域描述了資源所用的自然語言。沒有設定該域則認為實體內容將提供給所有的語言閱讀者。
Content-Length:實體報頭域用於指明實體正文的長度,以位元組方式儲存的十進位制數字來表示。
Last-Modified:實體報頭域用於指示資源的最後修改日期和時間。
Content-Type:實體報頭域用語指明發送給接收者的實體正文的媒體型別。
Expires:實體報頭域給出響應過期的日期和時間。為了讓代理伺服器或瀏覽器在一段時間以後更新快取中(再次訪問曾訪問過的頁面時,直接從快取中載入,縮短響應時間和降低伺服器負載)的頁面,我們可以使用Expires實體報頭域指定頁面過期的時間。
4.HTTP應用之常用前端頁面請求方式
(1) JQuery中的ajax請求: . p o s t ( U R L , d a t a , c a l l b a c k ) .post(URL,data,callback)和 .get(URL,callback)
$.get(URL,callback)
必需的 URL 引數規定您希望請求的 URL。
可選的 callback 引數是請求成功後所執行的函式名。
例如:

$("button").click(function(){
  $.get("demo_test.asp",function(data,status){
    alert("Data: " + data + "\nStatus: " + status);
  });
});

$.get() 的第一個引數是我們希望請求的 URL(“demo_test.asp”)。
第二個引數是回撥函式。第一個回撥引數存有被請求頁面的內容,第二個回撥引數存有請求的狀態。

$.post(URL,data,callback)
必需的 URL 引數規定您希望請求的 URL。
可選的 data 引數規定連同請求傳送的資料。
可選的 callback 引數是請求成功後所執行的函式名。
例如:

$("button").click(function(){
  $.post("demo_test_post.asp",
  {
    name:"Donald Duck",
    city:"Duckburg"
  },
  function(data,status){
    alert("Data: " + data + "\nStatus: " + status);
  });
});

$.post() 的第一個引數是我們希望請求的 URL (“demo_test_post.asp”)。
然後我們連同請求(name 和 city)一起傳送資料。
“demo_test_post.asp” 中的 ASP 指令碼讀取這些引數,對它們進行處理,然後返回結果。
第三個引數是回撥函式。第一個回撥引數存有被請求頁面的內容,而第二個引數存有請求的狀態。

區別:
GET - 方法通過 HTTP GET 請求從伺服器上請求資料,基本上用於從伺服器獲得(取回)資料。註釋:GET
方法可能返回快取資料。
POST - 方法通過 HTTP POST 請求從伺服器上請求資料,也可用於從伺服器獲取資料。不過,POST 方法
不會快取資料,並且常用於連同請求一起傳送資料。

(2) form表單提交請求:採用$(’#myform’).submit()方式發起請求;可以在form表單中的method中設定post方式還是get方式;例如:

<form enctype="application/x-www-form-urlencoded" action="http://" method="POST">
    <input type="text" name="name" value="homeway">
    <input type="text" name="key" value="nokey">
    <input type="submit" value="submit">
</form

(3)window.open(URL,name,specs,replace),開啟新頁面,不重新整理當前頁面,預設時get方式請求

URL 可選。開啟指定的頁面的URL。如果沒有指定URL,開啟一個新的空白視窗
name 可選。指定target屬性或視窗的名稱。支援以下值:
_blank - URL載入到一個新的視窗。這是預設
_parent - URL載入到父框架
_self - URL替換當前頁面
_top - URL替換任何可載入的框架集
name - 視窗名稱

specs 可選。一個逗號分隔的專案列表。支援以下值:
channelmode=yes|no|1|0 是否要在影院模式顯示 window。預設是沒有的。僅限IE瀏覽器
directories=yes|no|1|0 是否新增目錄按鈕。預設是肯定的。僅限IE瀏覽器
fullscreen=yes|no|1|0 瀏覽器是否顯示全屏模式。預設是沒有的。在全屏模式下的 window,還必須在影院
模式。僅限IE瀏覽器
height=pixels 視窗的高度。最小.值為100
left=pixels 該視窗的左側位置
location=yes|no|1|0 是否顯示地址欄位.預設值是yes
menubar=yes|no|1|0 是否顯示選單欄.預設值是yes
resizable=yes|no|1|0 是否可調整視窗大小.預設值是yes
scrollbars=yes|no|1|0 是否顯示滾動條.預設值是yes
status=yes|no|1|0 是否要新增一個狀態列.預設值是yes
titlebar=yes|no|1|0 是否顯示標題欄.被忽略,除非呼叫HTML應用程式或一個值得信賴的對話方塊.預設值是
yes
toolbar=yes|no|1|0 是否顯示瀏覽器工具欄.預設值是yes
top=pixels 視窗頂部的位置.僅限IE瀏覽器
width=pixels 視窗的寬度.最小.值為100
replace Optional.Specifies規定了裝載到視窗的 URL 是在視窗的瀏覽歷史中建立一個新條目,還是替換瀏覽歷史中的當前條目。支援下面的值:
true - URL 替換瀏覽歷史中的當前條目。
false - URL 在瀏覽歷史中建立新的條目。
例如:

function open_win(){
  	window.open("http://www.baidu.com");//在瀏覽器新視窗中開啟
}
function openwin(){
	mywindow=window.open(' ',' ','width=200,heigth=100');
	mywindow.document.write("<p>新的一個空白視窗</p>");
	mywindow.focus();
}

(4)window.location.href(url),重新定向到新頁面,並重新整理開啟的頁面,預設是get方式
不常用,我就不慢慢說明了。