本帖最后由 ganlinlao 于 2015-1-30 20:25 編輯
第6章、網(wǎng)絡(luò)篇
2、Access作為客戶端與web的交互能力的思考 坦白地說,作為一個超爛的菜鳥,我總愚蠢地認(rèn)為寫任何一個access應(yīng)用,都應(yīng)該具有網(wǎng)絡(luò)功能。沒有網(wǎng)絡(luò)功能的access應(yīng)用更象是一種自娛自樂。甚至我悲觀地認(rèn)為,如果access不具有強大的網(wǎng)絡(luò)交互能力的話,那么在不遠(yuǎn)的將來,它會很快走向消亡。而且我堅信,以后的Access應(yīng)該具有很強大的網(wǎng)絡(luò)交互能力,否則它確實沒有多少存在的意義。微軟在access2013中已經(jīng)開始嘗試了。 很可惜,在認(rèn)壇里這么多年來,極少人談及Access與網(wǎng)絡(luò)交互能力。似乎太多的人堅定地認(rèn)為access+SQLserver是唯一正確的方式。Access+SQL server是一種雙層結(jié)構(gòu),有它的便利的一面。也有它的一些的局限性。這種局限性包括:SQL server的安裝問題(在一些很小的應(yīng)用中,這會是一個問題,其它的不算是問題)。在線更新問題,拓展性問題(拓展起來不方便),office文檔管理問題(我了解到不少人嘗試想利用sqlserver的filestream讀取word或excel文件,但似乎問題很多而不可行),圖片等資源的更新問題……
雖然我們在access經(jīng)常使用com組件,整個windows到處都是,而vba也只支持com的對象。但com本質(zhì)是什么?我個人愚蠢地認(rèn)為com的核心能力之一是聚合能力。通過組件的聚合,通過接口,達(dá)到簡便地復(fù)用。而且我個人愚蠢地認(rèn)為網(wǎng)絡(luò)的核心功能之一就是聚集能力。不管是xml,webservice,還是其它的讓人眼花繚亂的新技術(shù),無非都是為了方便數(shù)據(jù)的聚集。在這一點上com組件和網(wǎng)絡(luò)有著驚人一致的一面。
當(dāng)談及access與web網(wǎng)絡(luò)交互能力時,有幾個概念是一定要厘清的。 1、有狀態(tài)和無狀態(tài)。Access與sql server的連接是一種有狀態(tài)的連接。而access與http的連接是一種無狀態(tài)的連接。但websock的出現(xiàn)可能會改變這種情況。 2、字符集。整個windows都是采用gbk字符集,access和sql server也是默認(rèn)以gbk作為默認(rèn)字符集,但web上,gbk只是一種可選的字符集,更多的是采用utf-8字符集,很可惜vba沒有簡便的函數(shù)處理utf-8字符集。 3、緩存問題。盡管access也有緩存,只要你打開一個mdb或acced,緩存就一定存在。但這個緩存和瀏覽器中的緩存,是兩個概念。
4、同步和異步:access打開本地的mdb或acced,access打開sql server,所有的recordset默認(rèn)是同步的。盡管你可以使用異步,但我很少見到有人使用異步。但在web的數(shù)據(jù)交互時,異步但會成為一個異常重要的問題。
5、相對路徑和絕對路徑:
為實現(xiàn)Http訪問,微軟提供了這么幾種API:
(1)Winsock,工作于網(wǎng)絡(luò)層和傳輸層的開發(fā)庫,對于編寫TCP,UDP,以及原始IP通信程序非常合適。函數(shù)原形也基本符合Unix socket標(biāo)準(zhǔn)。Windows平臺上的大多數(shù)程序,如QQ,訊雷等都基于其開發(fā)。
(2)ws2_32,是Winsock的升級版本,在兼容的基礎(chǔ)上增加了不符合Unix socket標(biāo)準(zhǔn),但更適合Windows平臺的庫函數(shù),一般以WSA*開頭。
現(xiàn)代的大多數(shù)Windows平臺程序也都開始依賴于此庫。
(3)WinInet,Windows Internet擴展庫,工作于應(yīng)用協(xié)議層,提供了http,ftp,gopher協(xié)議的實現(xiàn),為基于以上三種協(xié)議的程序開發(fā)提供基礎(chǔ)平臺,需要說明的是,盡管WinInet工作于應(yīng)用層,但其本身wininet.dll的實現(xiàn)并不依賴于winsock.dll或ws2_32.dll,而是獨立存在的。至少目前的版本是這樣;赪inInet的應(yīng)用程序最著名的例子就是IE了。
(4)WinHttp,也是工作于應(yīng)用協(xié)議層,提供了http協(xié)議的實現(xiàn)。看起來與WinInet有重復(fù)的部分,沒錯,WinHttp就是為了替換WinInet中的http部分的,它更加健壯穩(wěn)定,而且還為http服務(wù)器端開發(fā)提供了庫函數(shù)。如果進(jìn)行現(xiàn)代http的開發(fā),建議使用WinHTTP而不是WinInet。使用WinHTTP進(jìn)行開發(fā)的著名例子就是Google的瀏覽器Chrome,但是Chrome2.0以后版本google放棄了winhttp而是使用了自己開發(fā)的http庫,這也是為了使chrome實現(xiàn)跨平臺的重要舉措。另外,WinHttp.dll也不依賴于winsock或ws2_32,也是獨立運行的。
如果基于socket編程的話,Winows平臺與其它平臺函數(shù)基本相同,實現(xiàn)跨平臺比較容易。
wsock和wininet或winhttp也可以同時使用。
WinInet HttpSendRequest使用的事項
HttpSendRequest不支持異步模式,雖然API文檔說可以,但是在其它官方文章中已證實不可以;要用異步方式完成任務(wù),需要通過使用線程來自己封裝。
HttpSendRequest使用的INTERNETHANLE要每次通過HttpOpenRequest獲取,不能重用,否則可能會出現(xiàn)無法讀取返回數(shù)據(jù)或數(shù)據(jù)重復(fù)等錯誤;雖然API文檔說只要每次把上次的數(shù)據(jù)取完就可以,但這是經(jīng)歷了無數(shù)痛苦的unit test后換來的經(jīng)驗。
發(fā)送httpSendRequest后,需要使用InternetReadFile來讀取,重復(fù)多次讀,直到返回數(shù)據(jù)為0byte為止。
錯誤代碼在http://support.microsoft.com/kb/193625 ,API文檔中找不到。
什么是WinHTTP?
WinHTTP的全稱是Microsoft Windows HTTP Services,它提供給開發(fā)者一個HTTP客戶端應(yīng)用程序接口(API), 通過這種API借助HTTP協(xié)議給其他的HTTP服務(wù)器發(fā)送請求.
WinHTTP支持桌面應(yīng)用程序, Windows系統(tǒng)服務(wù), 和Windows服務(wù)器端應(yīng)用程序.
對于基于Microsoft.NET Framework的應(yīng)用程序, 不推薦使用WinHTTP服務(wù), 因為.NET Framework應(yīng)用程序應(yīng)該使用在System.Net命名空間下的網(wǎng)絡(luò)基礎(chǔ)設(shè)施類型.
WinHTTP提供了兩種編程方式, 一種是CC++的API, 另一種是COM組件.
WinHTTP與WinINet的區(qū)別
================
WinHTTP被設(shè)計為主要應(yīng)用在服務(wù)器端應(yīng)用程序的場景下, 讓服務(wù)器端應(yīng)用程序訪問HTTP服務(wù)器.
WinINet是一種更老的技術(shù), 它被設(shè)計為一個HTTP客戶端平臺, 用于交互式桌面應(yīng)用程序, 比如說IE, Office等.
服務(wù)器端應(yīng)用程序要求HTTP客戶端服務(wù)使用WinHTTP而不是WinINet.
WinHTTP和WinINet在微軟是由不同的團隊來提供支持的.
WinHTTP與Proxy
================
如果HTTP Proxy需要認(rèn)證(authentication), 那么HTTP Application會收到407(proxy requiresauthentication). 除了這個狀態(tài)碼, 代理服務(wù)器還會發(fā)送一個或更多的authenticate headers:“Proxy-Authenticate”. 這些信息足夠我們在network monitor trace中鑒定HTTP無法訪問是否是由于proxy需要認(rèn)證引起的了.
WinHTTP的proxy配置是存儲在注冊表鍵
HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVersionInternetSettingsConnectionsWinHttpSettings
當(dāng)中的, 修改和查看需要使用一個命令行工具proxycfg
下面來說說實現(xiàn)Http訪問的流程(基本上都一樣的流程):
1, 首先我們打開一個Session獲得一個HINTERNET session句柄;
2, 然后我們使用這個session句柄與服務(wù)器連接得到一個HINTERNET connect句柄;
3, 然后我們使用這個connect句柄來打開Http 請求得到一個HINTERNET request句柄;
4, 這時我們就可以使用這個request句柄來發(fā)送數(shù)據(jù)與讀取從服務(wù)器返回的數(shù)據(jù);
5, 最后依次關(guān)閉request,connect,session句柄。
|