哪吒2之魔童闹海|哪吒2之魔童归来免费观看|哪吒2在线观看|哪吒2魔童闹海电影免费观看|哪吒2免费观看完整版大电影|哪吒1免费观看完整版

新疆軟件開(kāi)發(fā)

本站首頁(yè) 軟件開(kāi)發(fā) 成功案例 公司新聞 公司簡(jiǎn)介 客服中心 軟件技術(shù) 網(wǎng)站建設(shè)
  您現(xiàn)在的位置: 新疆二域軟件開(kāi)發(fā)公司 >> 開(kāi)發(fā)語(yǔ)言 >> 文章正文

網(wǎng)絡(luò)編程中怎樣得知一次數(shù)據(jù)已經(jīng)收完?

     兩年前用.net 2.0做了一個(gè)反向代理服務(wù)器,在這兩年時(shí)間里,不斷修改BUG以及優(yōu)化性能,使得可用性大大提高。近來(lái)碰到一個(gè)功能需求,實(shí)在無(wú)法找出有效的解決辦法,只好上來(lái)請(qǐng)教各位高人。
    先說(shuō)說(shuō)反向代理的工作機(jī)理吧。
1、客戶(hù)端通過(guò)瀏覽器訪(fǎng)問(wèn)反向代理的時(shí)候,會(huì)發(fā)出一個(gè)HTTP請(qǐng)求,反向代理收到這個(gè)TCP連接的時(shí)候,建立一個(gè)新的會(huì)話(huà)用于處理這個(gè)請(qǐng)求(BeginAccept、EndAccept);
2、會(huì)話(huà)對(duì)象建立一個(gè)從客戶(hù)端接收數(shù)據(jù)的委托,開(kāi)始異步讀取數(shù)據(jù)(BeginRead);
3、取得數(shù)據(jù)時(shí),進(jìn)入異步讀取的回調(diào)函數(shù)中,開(kāi)始處理數(shù)據(jù)(EndRead);
4、檢查反向代理與服務(wù)器的連接是否已建立,如果沒(méi)有建立,那么需要先建立連接(ConnectServer),并建立服務(wù)器的異步讀取委托(BeginRead);
5、把數(shù)據(jù)異步寫(xiě)入服務(wù)器(BeginWrite);
6、重新建立客戶(hù)端異步讀取委托(BeginRead),回到3;
7、收到服務(wù)器返回?cái)?shù)據(jù)時(shí),處理后,異步寫(xiě)入客戶(hù)端(BeginWrite);
8、重新建立服務(wù)器異步讀取委托(BeginRead),回到7;

所有的數(shù)據(jù)傳輸,都使用異步來(lái)完成,而只需要在3和7處為業(yè)務(wù)編寫(xiě)數(shù)據(jù)處理代碼即可。
實(shí)際上,對(duì)于反向代理來(lái)說(shuō),只需要處理客戶(hù)端發(fā)來(lái)的數(shù)據(jù)就可以了,需要把HTTP的HOST頭替換為真實(shí)服務(wù)器,而對(duì)于服務(wù)器響應(yīng)的數(shù)據(jù),只需要原樣發(fā)送給客戶(hù)端就可以了。

在步驟3中,我們只知道當(dāng)前收到了客戶(hù)端發(fā)來(lái)的數(shù)據(jù),而不知道這個(gè)數(shù)據(jù)是不是Http請(qǐng)求頭,或者是完整的Http請(qǐng)求頭。幸好,對(duì)于反向代理來(lái)說(shuō),不需要關(guān)心是否是完整的Http請(qǐng)求頭,只需要檢查是否是Http請(qǐng)求頭,如果是,就修改Host即可。在這里,我假設(shè)Http請(qǐng)求的第一個(gè)數(shù)據(jù)包肯定是獨(dú)立的數(shù)據(jù)包,不會(huì)“粘”在TCP連接中上一次數(shù)據(jù)的后面,這樣就可以直接使用Http協(xié)議規(guī)定的格式來(lái)檢查這個(gè)數(shù)據(jù)包是否Http請(qǐng)求頭了。雖然這個(gè)假設(shè)沒(méi)有什么依據(jù),但它確實(shí)非常有效。

程序就這樣工作了兩年,沒(méi)有什么問(wèn)題。

但接下來(lái),問(wèn)題就出現(xiàn)了,有一個(gè)需求,要求能夠把服務(wù)器返回的頁(yè)面中的某個(gè)字符串替換為指定的字符串。比如我用反向代理指向博客園,我就需要把博客園頁(yè)面中所有使用了絕對(duì)路徑的連接修改為指向反向代理服務(wù)器的連接。這就要求在步驟7這里處理數(shù)據(jù),把數(shù)據(jù)轉(zhuǎn)為字符串,然后替換鏈接,然后才發(fā)往客戶(hù)端。

但步驟7每次收到的數(shù)據(jù)只是一個(gè)片段,而不是整個(gè)頁(yè)面的HTML。即使我們?cè)俅渭僭O(shè)Http響應(yīng)的第一個(gè)數(shù)據(jù)包是獨(dú)立的數(shù)據(jù)包,也只能識(shí)別哪些是響應(yīng)頭,哪些是數(shù)據(jù)體而已。也想過(guò)每一段數(shù)據(jù)轉(zhuǎn)為這一段的字符串進(jìn)行處理,但是,如果剛好某個(gè)字符被網(wǎng)絡(luò)層拆分到兩個(gè)TCP數(shù)據(jù)包里怎么辦?還有,想博客園這樣使用了gzip的,如果不接受完整個(gè)頁(yè)面的數(shù)據(jù),是無(wú)法解壓的;就算這兩種情況都不存在,而網(wǎng)絡(luò)層剛好在超鏈接的地方拆分?jǐn)?shù)據(jù)包怎么辦?

因此,最保守的做法就是拿到整個(gè)頁(yè)面數(shù)據(jù)再開(kāi)始處理。也想過(guò)Http響應(yīng)頭那里有個(gè)Content-Length指明內(nèi)容長(zhǎng)度的,但實(shí)際中,很多響應(yīng)根本就不到這個(gè)段。

我查看過(guò)HttpListener類(lèi)和HttpListenerRequest類(lèi),嘗試從中發(fā)現(xiàn)它是如何接受完一次請(qǐng)求(響應(yīng))的,可惜這兩個(gè)類(lèi)調(diào)用了大量NativeAPI,就無(wú)法得知了。

還有瀏覽器,它又是如何得知某次響應(yīng)是否已經(jīng)完成的呢?

還請(qǐng)各位高人多多指教!

這個(gè)代理已經(jīng)放到codeplex上,大家有興趣可以看看:http://www.codeplex.com/XProxy/

作者:新生命 | 文章來(lái)源:cnblogs | 更新時(shí)間:2008-3-10 17:27:31

  • 上一篇文章:

  • 下一篇文章:

  • 相關(guān)文章:
    使用Response.Redirect時(shí)ry失效 -asp.net中
    復(fù)制SQL 數(shù)據(jù)庫(kù)時(shí)的問(wèn)題
    怎樣的情況下 可以更新數(shù)據(jù)
    如何使用高效數(shù)據(jù)檢索優(yōu)化SQL Server應(yīng)用程序性能
    軟件技術(shù)
    · 開(kāi)發(fā)語(yǔ)言
    · Java技術(shù)
    · .Net技術(shù)
    · 數(shù)據(jù)庫(kù)開(kāi)發(fā)
    最新文章  
    ·搜集整理的asp.net的驗(yàn)證方
    ·各種FOR循環(huán)結(jié)構(gòu)的整理
    ·軟件項(xiàng)目開(kāi)發(fā)中應(yīng)該考慮那
    ·搜集整理的javascript sel
    ·軟件開(kāi)發(fā)中項(xiàng)目經(jīng)理有那些
    ·學(xué)習(xí)如何在Lambda表達(dá)式進(jìn)
    ·C++基礎(chǔ)知識(shí):結(jié)構(gòu)體數(shù)據(jù)的
    ·C#實(shí)現(xiàn)短信發(fā)送程序的例子
    ·sun最近修補(bǔ)了一部分java的
    ·rss定制的另外一種實(shí)現(xiàn)方式
    ·delphi實(shí)現(xiàn)利用arp欺騙來(lái)實(shí)
    ·基礎(chǔ)學(xué)習(xí):基于WF的流程框
    ·網(wǎng)絡(luò)編程中怎樣得知一次數(shù)
    ·如何逆序輸出單鏈表?
    ·軟件開(kāi)發(fā)過(guò)程中的性能設(shè)計(jì)
    關(guān)于我們 | 軟件開(kāi)發(fā) | 下載試用 | 客服中心 | 聯(lián)系我們 | 友情鏈接 | 網(wǎng)站地圖 | 新疆電子地圖 | RSS訂閱
    版權(quán)所有 © 2016 新疆二域軟件開(kāi)發(fā)網(wǎng) www.pg11qqq.com All Rights Reserved 新ICP備14003571號(hào)
    新疆軟件開(kāi)發(fā)總機(jī):0991-4842803、4811639.
    客服QQ:596589785 ;地址:新疆烏魯木齊北京中路華聯(lián)大廈A-5C 郵編:830000