JavaHttp多次請(qǐng)求復(fù)用同一連接示例詳解_第1頁(yè)
JavaHttp多次請(qǐng)求復(fù)用同一連接示例詳解_第2頁(yè)
JavaHttp多次請(qǐng)求復(fù)用同一連接示例詳解_第3頁(yè)
JavaHttp多次請(qǐng)求復(fù)用同一連接示例詳解_第4頁(yè)
JavaHttp多次請(qǐng)求復(fù)用同一連接示例詳解_第5頁(yè)
已閱讀5頁(yè),還剩3頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶(hù)提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

第JavaHttp多次請(qǐng)求復(fù)用同一連接示例詳解目錄概述復(fù)用的基本條件理論基礎(chǔ)現(xiàn)實(shí)基礎(chǔ)獲取HTTP資源常見(jiàn)方式Transfer-Encoding簡(jiǎn)略實(shí)現(xiàn)

概述

注:

本文乃是最簡(jiǎn)單的實(shí)現(xiàn),真實(shí)場(chǎng)景要復(fù)雜麻煩的多旨在闡述清晰多次HTTP請(qǐng)求復(fù)用一個(gè)連接的底層邏輯

早在HTTP/1.0時(shí)代,每次HTTP請(qǐng)求都要?jiǎng)?chuàng)建一個(gè)連接,而創(chuàng)建連接的過(guò)程需要消耗資源和時(shí)間,代價(jià)相對(duì)昂貴,為了減少資源消耗,縮短響應(yīng)時(shí)間,就需要重用連接。在后來(lái)的HTTP/1.1中,引入了連接復(fù)用的機(jī)制,HttpHeader中加入Connection:keep-alive來(lái)告訴對(duì)方這個(gè)請(qǐng)求響應(yīng)完成后先不忙關(guān)閉,這也是本篇文章的由來(lái)。

復(fù)用的基本條件

理論基礎(chǔ)

OSI是OpenSystemInterconnection的縮寫(xiě),意為開(kāi)放式系統(tǒng)互聯(lián)。國(guó)際標(biāo)準(zhǔn)化組織(ISO)制定了OSI模型,該模型定義了不同計(jì)算機(jī)互聯(lián)的標(biāo)準(zhǔn),是設(shè)計(jì)和描述計(jì)算機(jī)網(wǎng)絡(luò)通信的基本框架。也就是如下七層模型:

當(dāng)然也有大家熟知的五層模型,也就是把會(huì)話層、表示層、應(yīng)用層合稱(chēng)為應(yīng)用層。耳熟能詳?shù)腡CP、UDP屬于數(shù)量稀少的傳輸層協(xié)議。在這之上的應(yīng)用層協(xié)議百花齊放諸如:HTTP、SMTR、FTP......,然后很多中間件也自定義了通訊協(xié)議,比如Dubbo、Mysql。

讀到這里大家可能就已經(jīng)清醒的意識(shí)到,即使同屬應(yīng)用層的協(xié)議,是否支持長(zhǎng)連接也不盡相同。筆者想要傳達(dá)的一個(gè)認(rèn)知:之所以能支持長(zhǎng)連接,那是因?yàn)門(mén)CP經(jīng)歷三次握手建立連接之后,如果不出現(xiàn)其他意外是可以保證連接狀態(tài)的。也就是說(shuō)應(yīng)用層協(xié)議是否屬于長(zhǎng)連接僅僅取決于成功建立TCP,發(fā)送一個(gè)請(qǐng)求之后,對(duì)該連接的處理策略:

如早期的HTTP每次發(fā)送請(qǐng)求,Server端回復(fù)完畢之后直接關(guān)閉則是短連接如Mysql處理完一條SQL請(qǐng)求,然后繼續(xù)執(zhí)行下一個(gè)則是長(zhǎng)連接

這其實(shí)就是我們的理論基礎(chǔ),HTTP有希望支持長(zhǎng)連接的前提是TCP本身就是長(zhǎng)連接。

現(xiàn)實(shí)基礎(chǔ)

HTTP協(xié)議并非魔法,不是說(shuō)新增一條規(guī)范,也不是簡(jiǎn)簡(jiǎn)單單的Header中加入Connection:keep-alive就能立馬支持長(zhǎng)連接了。想要達(dá)到這個(gè)目的需要Client、Server端共同努力。

客戶(hù)端譬如Chrome瀏覽器,服務(wù)端譬如阿里OSS,像這樣兩端都支持了新的規(guī)范,HTTP才能快樂(lè)的成為長(zhǎng)連接陣營(yíng)中的一員。

獲取HTTP資源常見(jiàn)方式

因?yàn)镴DK提供了相關(guān)工具、且平臺(tái)相關(guān)的第三方包也足夠優(yōu)秀,所以Java獲取HTTP資源并非難事。

@Slf4j

publicclassSinaPicDownload{

/*微博上某個(gè)畫(huà)師的作品*/

staticfinalStringHTTP_URL="/mw2000/006jQ3i8ly1h5k50zujydj35k0334kjo.jpg";

/*下載之后放在顏如玉電腦的io文件下*/

staticfinalStringLOCAL="/Users/admin/io/靈魂蓮華-皎月.jpeg";

publicstaticvoidmain(String[]args){

try(

InputStreamin=newURL(HTTP_URL).openStream();

FileOutputStreamout=newFileOutputStream(LOCAL)

byte[]buffer=newbyte[10242];

intread;

while((read=in.read(buffer))-1){

out.write(buffer,0,read);

out.flush();

catch(Throwablee){

log.error("獲取HTTP資源失敗:",e);

配合Java7之后提供的try-with-resources語(yǔ)法糖,你甚至僅僅只需要不到二十行的代碼就可以輕而易舉的達(dá)到目的,但是缺點(diǎn)也顯而易見(jiàn),通過(guò)這種方法每次只能獲取一個(gè)資源,用完之后只能完畢。我當(dāng)時(shí)就在想,Java怎么實(shí)現(xiàn)一次連接多次請(qǐng)求呢?

Transfer-Encoding

筆者在上文提到的理論基礎(chǔ)上推測(cè)到肯定可以使用Java提供的Socket建立TCP連接,關(guān)鍵問(wèn)題是怎么跟Server端描述HTTP請(qǐng)求呢?

類(lèi)比到現(xiàn)實(shí)生活中,兩者能順暢交流必然要求雙方都可以聽(tīng)懂對(duì)方的語(yǔ)言。那HTTP有沒(méi)有一種Client、Server都能解析的規(guī)范呢,HTTPTransfer-Encoding正是在這種背景下應(yīng)運(yùn)而生。通俗的來(lái)講Transfer-Encoding就是一種雙方都約定好的格式,我按照這個(gè)格式Encoding,你按照這個(gè)格式Decoding,ta大概長(zhǎng)這個(gè)樣子:

可想而知?jiǎng)倓偒@取那張圖片資源的是時(shí)候,我們肯定是這么跟新浪微博服務(wù)端說(shuō)的:

聲明:

真實(shí)的RequestLine與圖中一致Header其實(shí)復(fù)雜很多,配圖做了簡(jiǎn)化該請(qǐng)求Body為空,圖中略過(guò)

簡(jiǎn)略實(shí)現(xiàn)

先聲明一些常量,以備后用

@Slf4j

publicclassReusableHttp{

/*顏如玉公司的OSS服務(wù)域名*/

staticfinalStringHOST="****.";

staticfinalintPORT=80;

/*顏如玉在OSS上放置的幾個(gè)資源*/

staticfinalString[]URLS=newString[]{

"/context/reusable/gtyj.text",

"/context/reusable/tlyxqch.text",

"/context/reusable/yj.text",

"/context/reusable/ls.text"

/*CR='\r';LF='\n'*/

staticfinalbyte[]CRLF=newbyte[]{Chars.CR,Chars.LF};

staticfinalStringLOCAL_PATH="/Users/admin/io/";

建立TCP連接,然后獲得輸出,輸入流

publicstaticvoidmain(String[]args){

try{

try(

Socketsocket=newSocket(HOST,PORT);

OutputStreamout=socket.getOutputStream();

InputStreamin=socket.getInputStream()

/*復(fù)用連接,獲取資源*/

reusable(out,in);

catch(IOExceptione){

log.error("請(qǐng)求出現(xiàn)異常",e);

寫(xiě)出RequestLine

/**

*WriteRequestLine

*RequestLineencoding規(guī)范

***********************************************

**method*sp*URL*sp*version*cr*lf*

***********************************************

staticvoidwriteRequestLine(OutputStreamout,Stringurl)throwsIOException{

/*注意空格一定要按照規(guī)定來(lái)擺放*/

out.write(("GET"+url+"HTTP/1.1").getBytes());

/*最后再寫(xiě)入一個(gè)回車(chē)、換行符表示RequestLine結(jié)束*/

out.write(CRLF);

寫(xiě)出RequestHeader

/**

*WriteRequestHeader

*HeaderLineencoding規(guī)范

********************************************

**headerfieldname*:*value*cr*lf*

********************************************

*....

********************************************

**headerfieldname*:*value*cr*lf*

********************************************

*...

************

**cr*lf*

************

****************

**EntityBody*

****************

staticvoidwriteHeaderLine(OutputStreamout)throwsIOException{

out.write("Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9".getBytes());

out.write(CRLF);

out.write("Accept-Encoding:gzip,deflate".getBytes());

out.write(CRLF);

out.write("Accept-Language:zh-CN,zh;q=0.9".getBytes());

out.write(CRLF);

out.write("Connection:keep-alive".getBytes());

out.write(CRLF);

out.write("Host:".getBytes());

out.write(CRLF);

/*最后再寫(xiě)入一個(gè)回車(chē)、換行符表示RequestHeader結(jié)束*/

out.write(CRLF);

因?yàn)槭呛?jiǎn)單的請(qǐng)求,所以直接省略RequestBody。發(fā)出如上報(bào)文后,Server端會(huì)解析請(qǐng)求,然后回復(fù)。

/**

*1.向Server端寫(xiě)出請(qǐng)求

*2.接受Server端回復(fù)

*3.寫(xiě)到顏如玉本地機(jī)器的io文件夾下

*@paramout往Server端寫(xiě)出流

*@paraminServer端往Client端寫(xiě)入流

staticvoidreusable(OutputStreamout,InputStreamin)throwsIOException{

for(inti=0,s=URLS.length;ii++){

writeRequestLine(out,URLS[i]);

writeHeaderLine(out);

out.flush();

byte[]bytes=newbyte[512];

in.read(bytes);

Stringfile=LOCAL_PATH+i+".te

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶(hù)所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶(hù)上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶(hù)上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶(hù)因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論