當前位置:首頁 > Web開發 > Ajax 技術 > 正文

深入顯出HTTP協議 - Ajax跨區訪問的研究與實現(研一作品)

深入淺出HTTP協議 - Ajax跨區訪問的研究與實現(研一作品) ? ?最近一些天來,由于實驗室項目開發的需要,自己對HTTP協議進行了比較細致的研究,并結合目前項目進度,成功解決了Ajax的跨域訪問問題! HTTP協議之深入淺出: ?HTTP-Hypertext Transfer Protocol(超文本傳輸協議),這是我們日常上網接觸最多的網絡應用層協議之一。有些朋友可能會問,這么個協議有什么值得研究的?非也,作為一個合格的軟件開發人員,具備一定的協議分析能力是必要的,也是必須的,而且深入地理解HTTP協議也有助于我們掌握Servlet和Jsp技術! “HTTP has been in use by the World-Wide Web global information initiative since 1990. This specification defines the protocol referred to as "HTTP/1.1", and is an update to RFC 2068 [33].” 下面,我們來看看Web中常用的術語,這對我們下面深入理解HTTP運行機理很有必要。瀏覽器(Browser)是Web應用的用戶代理,它用于顯示所請求的Web頁面,并且提供了大量的導航功能和配置屬性。因為Web瀏覽器是實現了HTTP協議的客戶端,所以根據不同的上下文環境,我們經常交替使用“瀏覽器”和“客戶機”來稱呼它。目前流行的Web瀏覽器包括Netscape Communicator 和Microsoft Internet Explorer。Web服務器用于存儲Web對象(簡單的說就是文件,如HTML文件,JPEG文件,GIF文件,Java小程序,聲音剪輯文件等),每個對象由URL尋址(通常有兩部分組成:存放對象的服務器主機名和對象的路徑名)。Web服務器實現了HTTP的服務器端,流行的Web服務器程序有Apache和Microsoft Internet Information Server(IIS)。 簡單的講,HTTP協議定義了瀏覽器如何向Web站點請求Web頁面以及服務器如何響應請求這一過程。它是一種無狀態的協議(Stateless),即服務器在向客戶機發送響應消息時并不存儲客戶機的任何狀態信息。 截至1997年,基本上所有的瀏覽器和服務器都實現的是在RFC 1945中定義的HTTP/1.0協議。從1998年開始,一些Web服務器和瀏覽器開始實現在RFC 2612中定義的HTTP/1.1 。HTTP/1.1協議向后兼容HTTP/1.0協議,它最大的特點是支持持久連接。HTTP使用TCP(而不是UDP)作為底層傳輸協議。在TCP連接上可以傳送多個HTTP請求和響應,減少了建立和關閉連接的消耗和延遲。它不必像HTTP/1.0協議中定義的那樣,為每一個請求對象建立和維護一個全新的連接。 持久連接又分為兩種方式:非流水線方式(without pipelining)和流水線方式(with pipelining)。在非流水線方式下,客戶機只能在前一個響應接收到之后才發出新的請求。在這種情況下,服務器發送完一個對象后,連接處于空閑狀態,等待下一個請求的到來,這勢必浪費了寶貴的服務器資源。 由于最近一直在做J2EE相關軟件開發,所以在本次的研究中,我使用了業界最為流行的輕量級Web容器Tomcat(5.5.25版本)作為Web服務器,至于我前面提到的Apache,它比較適合用PHP等Web程序設計語言開發項目的Web服務器,而IIS則比較適合于Asp,Asp.net項目的Web服務器。當然,Tomcat在處理靜態頁面時速度顯得稍微滿了些,不過還好,我們可以講Tomcat與Apache或者是IIS進行集成,需要的僅僅是一個JK插件(這個插件我還沒用過,所以不敢在這妄加評論,等以后項目中使用到了我想自己會認真研究一下,講心得貼出來與大家分享!)。在這我們還是用到了Telnet客戶端軟件,這個軟件默認是隨著Window操作系統一起被裝入機器的,唯一需要的是簡簡單單的一個Dos命令 net start telnet(當然這個命令是對于像我這種追求操作系統簡約而停掉一些不經常使用的服務的人有用的,呵呵!)。 在這,我要強調兩個容易混淆的概念:URI和URL。URI(Uniform Resource Identifier),它是一套符號結構,用于標識Web資源的各個組成部分。URL(Uniform Resource Locator)是一種特殊的URI,它標識了用于查找某個資源足夠的信息。而諸如:mailto:fengjia11@163.com則不屬于URL,我們只能稱其為URN(Uniform Resource Name,通用資源名)。為了將討論的重點放在其它上面,我們一般統稱它們為URL。 具體到HTTP報文的具體格式,我想在使用實例講解,大家比較容易理解。Ok,看看我下面的截圖。 ? ? 下面,對照著截圖,我們來一起看一下HTTP報文格式,HTTP協議是基于請求/響應模式的,請求報文的格式如下:請求行,消息報頭(請求報頭),請求正文。而請求行又有固定的格式,如上圖第一行所示,其分別對應著:方法字段,URL字段,HTTP協議版本字段。在HTTP/1.0中,只有三類方法,分別為:GET,POST,HEAD。除了這三個方法外,在HTTP/1.1中還定義了其它的方法,諸如:PUT,DELETE,TRACE等。其中PUT方法是被那些需要上傳對象到服務器端的應用程序所使用,當然編程人員也可以調用相關的API進行上傳下載的編程,其底層就是使用了PUT方法。HEAD方法類似GET方法,當服務器收到HEAD方法的請求時,會用一個HTTP報文進行響應,但是不返回請求對象。應用程序開發人員常使用此方法進行故障跟蹤。 由上圖我們可以看出在請求行中我使用的HTTP/1.0版本的協議,而下面的一張截圖中我使用了HTTP/1.1進行請求。兩者的區別在于,后者必須有個Host消息報頭字段,這是HTTP、1.1做出的重大改進,它可以支持對服務器虛擬站點的訪問,而這在HTTP/1.0中卻是不可以的。并且注意:消息報頭大小寫無關(與請求行不同),并且在開發Servlet程序時,使用指令response.SetHeader()進行相關報頭的設定。 好了,下面我們來看看響應報文的格式:狀態行,消息報頭(響應報頭),響應正文。如圖第三行所示。(第二行是一空行),其中200是狀態代碼,它由3個數字組成,表示請求是否被理解或被滿足。狀態代碼的第一個數字定義了響應的類別,后面兩個數字沒有具體定義。由于篇幅的影響,這些代碼具體代表的意思我就不詳細敘述了,朋友們若有興趣,可以參看RFC 2612文檔說明。其中代碼 200表示客戶端請求成功。 400表示客戶端請求有語法錯誤,不能被服務器理解。 401表示請求未經授權,這個錯誤在我在開發Asp程序時經常遇到,所以印象比較深刻。404表示請求的資源不存在。 500表示服務器發生不可預知錯誤,導致無法完成客戶端請求。 503表示服務器當前不能處理客戶端請求,稍后可能會恢復正常。 ?? ? ? ? ? ???? 到這,我想起了網絡課上的Java編程,為了寫好這篇文章,我又將當初成功編譯運行的程序進行了修改(大約200多行吧!),本想把截圖也貼出來,可是一想,由于博客無法上傳圖片,所以就放棄了當初的想法。奧,對了,這篇文章是我一口氣寫下來的,其中有些錯別字可能沒有糾正,不過自己會在以后的日子里繼續修改的!還是那句話:“沒有最好,只有更好!“ Ajax跨域訪問: ?Ajax技術中XHR對象其實可以理解為瀏覽器中的瀏覽器,它代替用戶使用的瀏覽器向服務器發出請求,并獲取數據,利用這一點我們可以直接讀取遠程網頁,但事實遠非如此簡單,讀取其他網站的請求屬于跨域訪問,對這種方式的訪問,不同的瀏覽器可能會有所不同!對于IE 6 瀏覽器,會彈出如下圖的的對話框,提醒用戶要進行跨域訪問,而FireFox對跨域訪問根本就不會執行! ? ? 為了解決跨域訪問的問題,可以在服務器端編寫一個代理程序,XHR對象直接向代理程序發出請求,由代理程序訪問遠程服務器,并返回用戶所需要的數據,這樣就可以成功解決Ajax跨域訪問的問題! 剛開始,自己動手進行代理程序的編寫,解決了問題!后來發現,Apache Jakarta Commos下的子項目HtttpClient也可以解決此問題! 解決思路一: 自己動手編寫Proxy程序,注意問題: ①字符串的拼接問題 ②中文亂碼問題 客戶端與傳統的Ajax不同之處在于字符串的拼接,當我們通過代理訪問外域中的資源時,URL往往會拼接成這樣: http://127.0.0.1//AjaxServer?url=http://192.168.88.155/Ajax/index.jsp?username=fengjia&password=123 第一個問號前是目前Ajax程序所在的服務器地址,而我現在想訪問師兄的機子上的某個頁面,比方說index.jsp頁面!很遺憾,這樣的拼接服務器無法解析,必須將第二個問號也轉換成&,為此,我們必須解決字符串拼接問題,具體代碼如下圖: ? ? 好了,我們看看服務器端是怎么實現的吧,實現思路如下: ??? 首先,要提取用戶請求參數,對提交到同域下的請求和跨域下的URL請求要給予分別處理。 其次,根據服務器所接收參數的方式,決定使用GET或是POST方式生成新的請求字符串或請求體。當雙方服務器對字符采用不同的編碼時,還要進行字符編碼的轉換。 接下來,打開一個輸入流,接收來自服務器的響應,并且分析響應頭的內容,以確定對方對數據的處理是否成功完成,并且將處理結果返回給用戶。 具體代碼如下圖: ? 解決思路二:使用HttpClient組件作為代理程序,代碼如下: String url = request.getParameter("url"); ??????????? HttpClient client = new HttpClient(); ??????????? GetMethod method = new GetMethod(url); ??????????? try{ ??????????????? client.executeMethod(method); ??????????????? out.println(method.getResponseBodyAsString()); ??????????? }catch(Exception e){ ??????????????? method.releaseConnection(); ??????????? } 總結: Ajax跨域訪問是個比較復雜的問題,在具體的項目工作中,為了保證系統的健壯性,需要對多方面進行細致考慮,隨著自己對Ajax技術的深入研究,技術日志會繼續推新的!
友情鏈接
異常 - Exception - Copyright © 2014 - 2014 - 開發異常網 - 鄂ICP備14001750號 - 網站地圖
乐客彩彩票 仁化县 | 芷江 | 阿勒泰市 | 龙泉市 | 昌吉市 | 舒兰市 | 淮滨县 | 光山县 | 利川市 | 沈丘县 | 宿州市 | 中阳县 | 吉木萨尔县 | 离岛区 | 浦北县 | 吉水县 | 探索 | 黔西 | 安塞县 | 团风县 | 达日县 | 池州市 | 象州县 | 米林县 | 兴海县 | 珲春市 | 天柱县 | 垫江县 | 田东县 | 嘉鱼县 | 宝山区 | 井陉县 | 普兰县 | 沐川县 | 九台市 | 云南省 | 交口县 | 中方县 | 定日县 | 泉州市 | 平果县 | 成都市 | 施秉县 | 年辖:市辖区 | 甘泉县 | 平泉县 | 辽源市 | 昌吉市 | 桃江县 | 马鞍山市 | 县级市 | 宣恩县 | 阿拉善左旗 | 江华 | 巴塘县 | 吴江市 | 沂南县 | 新津县 | 吴旗县 | 玛多县 | 会理县 | 拉萨市 | 三穗县 | 夹江县 | 平潭县 | 怀安县 | 和政县 | 绿春县 | 盐城市 | 拉萨市 | 海门市 | 兖州市 | 扎赉特旗 | 合肥市 | 五华县 | 河池市 | 佛山市 | 通江县 | 海口市 | 新密市 | 七台河市 | 夏河县 | 沅陵县 | 昌图县 | 大新县 | 伊金霍洛旗 | 延长县 | 怀来县 | 金坛市 | 秭归县 | 商河县 | 靖西县 | 洞口县 | 色达县 | 和政县 | 永昌县 | 昌都县 | 信宜市 | 绥滨县 | 兴隆县 | 江门市 | 扎鲁特旗 | 墨玉县 | 冕宁县 | 澄江县 | 江安县 | 许昌市 | 个旧市 | 台州市 | 仪陇县 | 维西 | 郑州市 | 纳雍县 | 会宁县 | 古浪县 | 盐津县 | 金阳县 | 永宁县 | 孝昌县 | 平谷区 | 正宁县 | 衡东县 | 共和县 | 宁晋县 | 江口县 | 玉田县 | 公安县 | 成武县 | 韶关市 | 石棉县 | 儋州市 | 信宜市 | 辉县市 | 上饶市 | 白山市 | 东乡族自治县 | 昂仁县 | 柳州市 | 黑河市 | 彭州市 | 赤峰市 | 蒙山县 | 夏河县 | 东光县 | 济宁市 | 西吉县 | 新和县 | 长乐市 | 莲花县 | 郁南县 | 肥城市 | 文成县 | 盘锦市 | 康平县 | 剑川县 | 连江县 | 石河子市 | 济宁市 | 滦南县 | 琼中 | 丰都县 | 永吉县 | 嘉鱼县 | 永州市 | 玉山县 | 分宜县 | 会昌县 | 康保县 | 精河县 | 双流县 | 甘德县 | 钦州市 | 靖宇县 | 紫金县 | 甘孜 | 安徽省 | 息烽县 | 桃园市 | 延吉市 | 临高县 | 石阡县 | 石泉县 | 乌鲁木齐县 | 谷城县 | 泰和县 | 兴化市 | 凌海市 | 福海县 | 贺州市 | 喀喇沁旗 | 全州县 | 肥乡县 | 资兴市 | 沾益县 | 凉山 | 玉屏 | 台中县 | 临城县 | 侯马市 | 伊春市 | 新巴尔虎左旗 | 新郑市 | 增城市 | 郁南县 | 牡丹江市 | 盈江县 | 岳阳市 | 聊城市 | 库尔勒市 | 松溪县 | 碌曲县 | 南京市 | 婺源县 | 宁乡县 | 耒阳市 | 城口县 | 永兴县 | 兴宁市 | 大渡口区 | 双桥区 | 江陵县 | 鹤岗市 | 八宿县 | 仁化县 | 苏州市 | 古浪县 | 昆山市 | 天峨县 | 卢湾区 | 济源市 | 昭苏县 | 昔阳县 | 漳州市 | 清丰县 | 鄄城县 | 铜陵市 | 武义县 | 莱州市 | 分宜县 | 潍坊市 | 武宁县 | 宾川县 | 海阳市 | 和田市 | 平原县 | 镇安县 | 杨浦区 | 通山县 | 白水县 | 鄯善县 | 沁水县 |