網(wǎng)絡編程
- Java基礎(chǔ):網(wǎng)絡編程
- Uri率挣、URL清寇、UriMatcher浩村、ContentUris詳解
- Android應用開發(fā):網(wǎng)絡編程1
- Android應用開發(fā):網(wǎng)絡編程2
1. 什么是HTTP協(xié)議
客戶端連上web服務器后做葵,若想獲得web服務器中的某個web資源,需遵守一定的通訊格式心墅,HTTP協(xié)議用于定義客戶端與web服務器通迅的格式蜂挪。
HTTP是hypertext transfer protocol(超文本傳輸協(xié)議)的簡寫重挑,它是TCP/IP協(xié)議的一個應用層協(xié)議,用于定義WEB瀏覽器與WEB服務器之間交換數(shù)據(jù)的過程棠涮。這個協(xié)議詳細規(guī)定了瀏覽器和萬維網(wǎng)服務器之間互相通信的規(guī)則谬哀。
HTTP就是一個通信規(guī)則,通信規(guī)則規(guī)定了客戶端發(fā)送給服務器的內(nèi)容格式严肪,也規(guī)定了服務器發(fā)送給客戶端的內(nèi)容格式史煎。其實我們要學習的就是這個兩個格式!客戶端發(fā)送給服務器的格式叫“請求協(xié)議”驳糯;服務器發(fā)送給客戶端的格式叫“響應協(xié)議”篇梭。
HTTP協(xié)議是學習JavaWEB開發(fā)的基石,不深入了解HTTP協(xié)議酝枢,就不能說掌握了WEB開發(fā)恬偷,更無法管理和維護一些復雜的WEB站點。
OSI網(wǎng)絡七層協(xié)議
應用層(HTTP帘睦、FTP袍患、SMTP、POP3竣付、TELNET)->表示層->會話層->傳輸層(TCP诡延、UDP)->網(wǎng)絡層(IP)->數(shù)據(jù)鏈路層->物理層
2. HTTP協(xié)議簡介
HTTP使用請求-響應的方式進行傳輸,一個請求對應一個響應古胆,并且請求只能是由客戶端發(fā)起的肆良。
利用Telnet演示請求與響應的過程
安裝IE瀏覽器插件HttpWatch,查看IE瀏覽器通過HTTP協(xié)議獲取某個頁面逸绎。
HTTP協(xié)議的版本:HTTP/1.0惹恃、HTTP/1.1
3. HTTP1.0和HTTP1.1的區(qū)別
在HTTP1.0協(xié)議中,客戶端與web服務器建立連接后棺牧,只能獲得一個web資源巫糙。
HTTP1.1協(xié)議,允許客戶端與web服務器建立連接后陨帆,在一個連接上獲取多個web資源曲秉。
利用telnet演示HTTP1.0和HTTP1.1的區(qū)別
一個好多同學搞不清楚的問題:
一個web頁面中采蚀,使用img標簽引用了三幅圖片疲牵,當客戶端訪問服務器中的這個web頁面時,客戶端總共會訪問幾次服務器榆鼠,即向服務器發(fā)送了幾次HTTP請求纲爸。
4. 協(xié)議
協(xié)議:協(xié)議的甲乙雙方,就是客戶端(瀏覽器)和服務器妆够!
理解成雙方通信的格式识啦!
- 請求協(xié)議
- 響應協(xié)議
5. HttpWatch和FireBug
HttpWatch是專門為IE瀏覽器提供的负蚊,用來查看HTTP請求和響應內(nèi)容的工具。而FireFox上需要安裝FireBug軟件颓哮。如果你使用的是Chrome家妆,那么就不用自行安裝什么工具了,因為它自身就有查看請求和響應內(nèi)容的功能冕茅!
HttpWatch和FireBug這些工具對瀏覽器而言不是必須的伤极,但對我們開發(fā)者是很有幫助的,通過查看HTTP請求響應內(nèi)容姨伤,可以使我們更好的學習HTTP協(xié)議哨坪。
6. 請求協(xié)議
請求協(xié)議的格式如下:
請求首行;
請求頭信息乍楚;
空行当编;
請求體。
瀏覽器發(fā)送給服務器的內(nèi)容就這個格式的徒溪,如果不是這個格式服務器將無法解讀忿偷!在HTTP協(xié)議中,請求有很多請求方法词渤,其中最為常用的就是GET和POST牵舱。不同的請求方法之間的區(qū)別,后面會一點一點的介紹缺虐。
6.1 GET請求
打開IE芜壁,在訪問hello項目的index.jsp之間打開HttpWatch,并點擊“Record”按鈕高氮。然后訪問index.jsp頁面慧妄。查看請求內(nèi)容如下:
GET /hello/index.jsp HTTP/1.1
Host: localhost
User-Agent: Mozilla/5.0 (Windows NT 5.1; rv:5.0) Gecko/20100101 Firefox/5.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-cn,zh;q=0.5
Accept-Encoding: gzip, deflate
Accept-Charset: GB2312,utf-8;q=0.7,*;q=0.7
Connection: keep-alive
Cookie: JSESSIONID=369766FDF6220F7803433C0B2DE36D98
GET /hello/index.jsp HTTP/1.1:GET請求,請求服務器路徑為/hello/index.jsp剪芍,協(xié)議為1.1
Host:localhost:請求的主機名為localhost
User-Agent: Mozilla/5.0 (Windows NT 5.1; rv:5.0) Gecko/20100101 Firefox/5.0:
與瀏覽器和OS相關(guān)的信息塞淹。有些網(wǎng)站會顯示用戶的系統(tǒng)版本和瀏覽器版本信息,這都是通過獲取User-Agent頭信息而來的Accept: text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8:
告訴服務器罪裹,當前客戶端可以接收的文檔類型饱普,其實這里包含了/,就表示什么都可以接收Accept-Language: zh-cn,zh;q=0.5
當前客戶端支持的語言状共,可以在瀏覽器的工具?選項中找到語言相關(guān)信息Accept-Encoding: gzip, deflate:支持的壓縮格式套耕。數(shù)據(jù)在網(wǎng)絡上傳遞時,可能服務器會把數(shù)據(jù)壓縮后再發(fā)送
Accept-Charset: GB2312,utf-8;q=0.7,*;q=0.7:客戶端支持的編碼
Connection: keep-alive:客戶端支持的鏈接方式峡继,保持一段時間鏈接冯袍,默認為3000ms
Cookie: JSESSIONID=369766FDF6220F7803433C0B2DE36D98
因為不是第一次訪問這個地址,所以會在請求中把上一次服務器響應中發(fā)送過來的Cookie在請求中一并發(fā)送去過;這個Cookie的名字為JSESSIONID康愤,然后在講會話是講究它儡循!
6.2 POST請求
為了演示POST請求,我們需要修改index.jsp頁面征冷,即添加一個表單:
<form action="" method="post">
關(guān)鍵字:<input type="text" name="keyword"/>
<input type="submit" value="提交"/>
</form>
打開HttpWatch择膝,輸入hello后點擊提交,查看請求內(nèi)容如下:
POST /hello/index.jsp HTTP/1.1
Accept: image/gif, image/jpeg, image/pjpeg, image/pjpeg, application/msword, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/x-ms-application, application/x-ms-xbap, application/vnd.ms-xpsdocument, application/xaml+xml, */*
Referer: http://localhost:8080/hello/index.jsp
Accept-Language: zh-cn,en-US;q=0.5
User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; InfoPath.2; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)
Content-Type: application/x-www-form-urlencoded
Accept-Encoding: gzip, deflate
Host: localhost:8080
Content-Length: 13
Connection: Keep-Alive
Cache-Control: no-cache
Cookie: JSESSIONID=E365D980343B9307023A1D271CC48E7D
keyword=hello
POST請求是可以有體的,而GET請求不能有請求體。
Referer: http://localhost:8080/hello/index.jsp
請求來自哪個頁面趟咆,例如你在百度上點擊鏈接到了這里,那么Referer:http://www.baidu.com每庆;如果你是在瀏覽器的地址欄中直接輸入的地址,那么就沒有Referer這個請求頭了Content-Type: application/x-www-form-urlencoded
表單的數(shù)據(jù)類型今穿,說明會使用url格式編碼數(shù)據(jù)缤灵;url編碼的數(shù)據(jù)都是以“%”為前綴,后面跟隨兩位的16進制蓝晒,例如“傳智”這兩個字使用UTF-8的url編碼用為“%E4%BC%A0%E6%99%BA”Content-Length:13:請求體的長度腮出,這里表示13個字節(jié)
keyword=hello:請求體內(nèi)容!hello是在表單中輸入的數(shù)據(jù)芝薇,keyword是表單字段的名字胚嘲。
Referer請求頭是比較有用的一個請求頭,它可以用來做統(tǒng)計工作洛二,也可以用來做防盜鏈馋劈。
6.3 統(tǒng)計工作
我公司網(wǎng)站在百度上做了廣告,但不知道在百度上做廣告對我們網(wǎng)站的訪問量是否有影響晾嘶,那么可以對每個請求中的Referer進行分析妓雾,如果Referer為百度的很多,那么說明用戶都是通過百度找到我們公司網(wǎng)站的垒迂。
6.4 防盜鏈
我公司網(wǎng)站上有一個下載鏈接械姻,而其他網(wǎng)站盜鏈了這個地址,例如在我網(wǎng)站上的index.html頁面中有一個鏈接机断,點擊即可下載JDK7.0楷拳,但有某個人的微博中盜鏈了這個資源,它也有一個鏈接指向我們網(wǎng)站的JDK7.0吏奸,也就是說登錄它的微博欢揖,點擊鏈接就可以從我網(wǎng)站上下載JDK7.0,這導致我們網(wǎng)站的廣告沒有看苦丁,但下載的卻是我網(wǎng)站的資源浸颓。這時可以使用Referer進行防盜鏈物臂,在資源被下載之前旺拉,我們對Referer進行判斷产上,如果請求來自本網(wǎng)站,那么允許下載蛾狗,如果非本網(wǎng)站晋涣,先跳轉(zhuǎn)到本網(wǎng)站看廣告,然后再允許下載
7. 響應協(xié)議
7.1 響應內(nèi)容
響應協(xié)議的格式如下:
響應首行沉桌;
響應頭信息谢鹊;
空行;
響應體留凭。
響應內(nèi)容是由服務器發(fā)送給瀏覽器的內(nèi)容佃扼,瀏覽器會根據(jù)響應內(nèi)容來顯示。
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Content-Type: text/html;charset=UTF-8
Content-Length: 724
Set-Cookie: JSESSIONID=C97E2B4C55553EAB46079A4F263435A4; Path=/hello
Date: Wed, 25 Sep 2012 04:15:03 GMT
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="http://localhost:8080/hello/">
<title>My JSP 'index.jsp' starting page</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->
</head>
<body>
<form action="" method="post">
關(guān)鍵字:<input type="text" name="keyword"/>
<input type="submit" value="提交"/>
</form>
</body>
</html>
- HTTP/1.1 200 OK:響應協(xié)議為HTTP1.1蔼夜,狀態(tài)碼為200兼耀,表示請求成功,OK是對狀態(tài)碼的解釋
- Server: Apache-Coyote/1.1:服務器的版本信息
- Content-Type: text/html;charset=UTF-8:響應體使用的編碼為UTF-8
- Content-Length: 724:響應體為724字節(jié)
- Set-Cookie: JSESSIONID=C97E2B4C55553EAB46079A4F263435A4; Path=/hello:響應給客戶端的Cookie求冷;
- Date: Wed, 25 Sep 2012 04:15:03 GMT:響應的時間瘤运,這可能會有8小時的時區(qū)差
7.2 若干響應頭
響應頭 | 功能描述 |
---|---|
Content-Encoding: gzip | 服務器發(fā)送數(shù)據(jù)時使用的壓縮格式 |
Server:apache tomcat | 服務器的基本信息 |
Content-Length: 80 | 發(fā)送數(shù)據(jù)的大小 |
Content-Language: zh-cn | 發(fā)送的數(shù)據(jù)使用的語言環(huán)境 |
Content-Disposition: attachment;filename=aaa.zip | 與下載相關(guān)的頭 |
Expires: -1 | 指定資源緩存的時間,如果取值為0或-1瀏覽就不緩存資源 |
Cache-Control: no-cache | 緩存相關(guān)的頭匠题,如果為no-cache則通知瀏覽器不緩存 |
Pragma: no-cache | 緩存相關(guān)的頭拯坟,如果為no-cache則不緩存 |
Connection: close/Keep-Alive | 是否保持連接 |
Location | 配合302實現(xiàn)請求重定向 |
Content-Type | 發(fā)送數(shù)據(jù)的類型和編碼 |
Last-Modified | 最后修改時間 |
Refresh | 自動刷新,n秒后跳轉(zhuǎn)到另一個頁面 |
Set-Cookie | 發(fā)送Cookie信息 |
Location: http://www.it315.org/index.jsp 配合302實現(xiàn)請求重定向
Content-Type: text/html; charset=GB2312 當前所發(fā)送的數(shù)據(jù)的基本信息韭山,(數(shù)據(jù)的類型郁季,所使用的編碼)
Last-Modified: Tue, 11 Jul 2000 18:23:51 GMT 緩存相關(guān)的頭
Refresh: 1;url=http://www.it315.org 通知瀏覽器進行定時刷新,此值可以是一個數(shù)字指定多長時間以后刷新當前頁面钱磅,這個數(shù)字之后也可以接一個分號后跟一個URL地址指定多長時間后刷新到哪個URL
Transfer-Encoding: chunked 傳輸類型巩踏,如果是此值是一個chunked說明當前的數(shù)據(jù)是一塊一塊傳輸?shù)?/p>
Set-Cookie:SS=Q0=5Lb_nQ; path=/search 和cookie相關(guān)的頭,后面課程單講
ETag: W/"83794-1208174400000" 和緩存機制相關(guān)的頭
?
Date: Tue, 11 Jul 2000 18:23:51 GMT 當前時間
7.3 響應碼
響應頭對瀏覽器來說很重要续搀,它說明了響應的真正含義塞琼。例如200表示響應成功了,302表示重定向禁舷,這說明瀏覽器需要再發(fā)一個新的請求彪杉。
響應碼 | 描述 |
---|---|
200 | 請求成功,瀏覽器會把響應體內(nèi)容(通常是html)顯示在瀏覽器中 |
206 | 請求部分資源牵咙,和請求頭Range使用 |
302 | 重定向派近,當響應碼為302時,表示服務器要求瀏覽器重新再發(fā)一個請求洁桌, 服務器會發(fā)送一個響應頭Location渴丸,它指定了新請求的URL地址 |
304 | 服務器通知瀏覽器使用緩存 |
307 | 服務器通知瀏覽器使用緩存 |
404 | 請求的資源沒有找到,說明客戶端錯誤的請求了不存在的資源 |
500 | 請求資源找到了,但服務器內(nèi)部出現(xiàn)了錯誤 |
304:當用戶第一次請求index.html時谱轨,服務器會添加一個名為Last-Modified響應頭戒幔,這個頭說明了index.html的最后修改時間,瀏覽器會把index.html內(nèi)容土童,以及最后響應時間緩存下來诗茎。當用戶第二次請求index.html時,在請求中包含一個名為If-Modified-Since請求頭献汗,它的值就是第一次請求時服務器通過Last-Modified響應頭發(fā)送給瀏覽器的值敢订,即index.html最后的修改時間,If-Modified-Since請求頭就是在告訴服務器罢吃,我這里瀏覽器緩存的index.html最后修改時間是這個楚午,您看看現(xiàn)在的index.html最后修改時間是不是這個,如果還是尿招,那么您就不用再響應這個index.html內(nèi)容了醒叁,我會把緩存的內(nèi)容直接顯示出來。而服務器端會獲取If-Modified-Since值泊业,與index.html的當前最后修改時間比對把沼,如果相同,服務器會發(fā)響應碼304吁伺,表示index.html與瀏覽器上次緩存的相同饮睬,無需再次發(fā)送,瀏覽器可以顯示自己的緩存頁面篮奄,如果比對不同捆愁,那么說明index.html已經(jīng)做了修改,服務器會響應200
響應頭:
- Last-Modified:最后的修改時間
請求頭
- If-Modified-Since:把上次請求的index.html的最后修改時間還給服務器窟却;狀態(tài)碼:304昼丑,比較If-Modified-Since的時間與文件真實的時間一樣時,服務器會響應304夸赫,而且不會有響正文菩帝,表示瀏覽器緩存的就是最新版本
7.4 其他響應頭
1、告訴瀏覽器不要緩存的響應頭
- Expires: -1
- Cache-Control: no-cache
- Pragma: no-cache
以上三個頭都是用來控制緩存的茬腿,是因為歷史原因造成的呼奢,不同的瀏覽器認識不同的頭,我們通常三個一起使用保證通用性
2切平、自動刷新響應頭握础,瀏覽器會在3秒之后請求http://www.itcast.cn:
- Refresh: 3;url=http://www.itcast.cn
7.5 HTML中指定響應頭
在HTMl頁面中可以使用<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">來指定響應頭,例如在index.html頁面中給出<meta http-equiv="Refresh" content="3;url=http://www.itcast.cn">悴品,表示瀏覽器只會顯示index.html頁面3秒禀综,然后自動跳轉(zhuǎn)到http://www.itcast.cn简烘。
8. 模擬網(wǎng)絡請求
restClient,這個是firefox上的一個插件定枷,對應chrome瀏覽器叫做postman孤澎,這個插件主要用作和服務器開發(fā)人員聯(lián)調(diào)協(xié)議
postman
restClient
9. 測試請求的地址
10. gzip壓縮
一種壓縮格式,一種壓縮方式依鸥,可以對網(wǎng)絡傳輸?shù)臄?shù)據(jù)進行壓縮。減少網(wǎng)絡傳輸?shù)拇笮?/p>
為什么需要壓縮?因為經(jīng)過壓縮悼沈,可以減少體積贱迟,提高傳輸速度,提高用戶體驗
瀏覽器發(fā)送器請求的過程
- 1.發(fā)送請求頭:Accept-Encoding:gzip
- 2.服務器壓縮數(shù)據(jù),返回數(shù)據(jù),在響應頭里面添加Content-Encoding:gzip
- 3.客戶端,根據(jù)Content-Encoding這個響應頭,對應解壓
- 有Content-Encoding:gzip-->gzip解壓
- 沒有Content-Encoding:gzip-->標準解壓
app使用gzip壓縮:返回的json/xml(文本信息)其實就是個特殊的網(wǎng)頁,其實也是可以進行g(shù)zip壓縮
gzip壓縮效果
通過數(shù)據(jù),我們得知絮供,文本的壓縮率衣吠,大概可以達到70%左右。壓縮率很高
gzip壓縮的實現(xiàn)
try {
boolean isGzip = false;
//1.創(chuàng)建httpclient
DefaultHttpClient httpClient = new DefaultHttpClient();
//2.創(chuàng)建get請求
HttpGet get = new HttpGet("http://httpbin.org/gzip");
//① 添加請求頭 Accept-Encoding:"gzip, deflate"
get.addHeader("Accept-Encoding", "gzip");
//3.執(zhí)行請求
HttpResponse response = httpClient.execute(get);
if (response.getStatusLine().getStatusCode() == 200) {
//② 得到響應頭,Content-Encoding:"gzip"
Header[] headers = response.getHeaders("Content-Encoding");
for (Header header : headers) {
if (header.getValue().equals("gzip")) {//后臺server把數(shù)據(jù)進行了gzip壓縮
isGzip = true;
}
}
String result = "";
HttpEntity entity = response.getEntity();
//③根據(jù)是否使用gzip壓縮.采取不同的解壓方式
if (isGzip) {
//④進行g(shù)zip的解壓
GZIPInputStream in = new GZIPInputStream(response.getEntity().getContent());
//in-->string
result = convertStreamToString(in);
} else {
//4.打印結(jié)果
result = EntityUtils.toString(entity);
}
System.out.println("result:" + result);
}
} catch (Exception e) {
e.printStackTrace();
}
11. 抓包
11.1 Fiddler
只能抓瀏覽器返回的包壤靶,即只可以抓PC上的包缚俏,無法抓手機上的包
11.2 Wireshark
世界上最流行的網(wǎng)絡協(xié)議分析器,抓包工具Wireshark基本介紹和學習TCP三次握手
通過ping命令拿到網(wǎng)址的IP