利用Win32的網路函式建立一個網路瀏覽器 (轉)
利用的建立一個網路
Dale Rogerson
網路開發技術小組
摘要
這篇技術性文章討論瞭如何利用Microsoft Win32網路函式建立一個網路瀏覽器。這篇文章的宗旨是讓讀者瞭解一些Win32網路函式的作用、能力和使用範圍,而不是為這些功能給出一個詳細的文件。這篇文章所配合的SurfBear樣本應用使用Win32網路函式從網路上讀取HTML,並把它們顯示成原始的、沒有經過格式化的文字。
介紹
不透過網路,你就無法瞭解我的一個朋友。雜誌已經在inte上設定了電子期刊,而本地的報紙也已經把整個段落都放到了網路上。事實上,許多報紙都在聯機。每個人都有一個主頁,甚至一些無家可歸的人都有一個主頁。雖然有許多關於網路的訊息難免言過其實,但網路正在變成計算機整體的一部分已經是無庸置疑的了。
Microsoft 已經介紹了Microsoft Win32網路函式來協助開發者把網路變成他們的應用程式的整體部分。這些新的功能簡化了使用()、和HTTP(超文字傳輸協議)訪問網路。使用Win32網路函式的開發者不需要對或 配件。對於一些最普通的操作,開發者不需要知道他們正在使用的某個協議的細節。
最終,Win32網路函式將成為Win32應用程式介面的一部分並且與基於Windows的不同的平臺一起釋出。最初,Win32網路函式將在一個叫做WININET.DLL的再分散式動態連結庫裡。(來自Microsoft網路開發工具包,其網址是:)。這屬於網路開發工具包的一部分。
這篇文章說明了如何使用Win32網路函式去建立一個簡單的網路瀏覽器。它沒有具體詳細的討論這些功能的細節,但對他們的用法和操作給出了一個演示。請參考網址是/intdev/sdk/docs/wininet的Microsoft Win32網路函式的主題,可以瞭解到全部的細節。
這篇文章是配合SurfBear樣本應用程式而創作的。SurfBear是一個HTML檔案。覆蓋了這個過程種特定的網路部分,但它沒有涉及與這個過程有關的介面問題或HTML檔案的顯示或操作問題。
注意:這篇文章是基於WININET.DLL一個相當早的版本。很可能其中的引數名、標識名和函式名發生了改變。但是函式的範圍和意圖應該還是和這篇文章中描述的是一致的。
網路函式
最好的探討Win32網路函式的方法是直接進入程式碼。下面的程式碼是樣本的程式碼,為了方便閱讀,錯誤處理部分已經被刪除掉了。
HINTERNET = ::InternetOpen("MSDN SurfBear",
PRE_CONFIG_INTERNET_ACCESS,
NULL,
INTERNET_INVALID_PORT_NUMBER,
0) ;
HINTERNET hUrlFile = ::InternetOpenUrl(hNet,
"",
NULL,
0,
INTERNET_FLAG_RELOAD,
0) ;
char buffer[10*1024] ;
D dwBytesRead = 0;
BOOL bRead = ::InternetReadFile(hUrlFile,
buffer,
sizeof(buffer),
&dwBytesRead);
::InternetCloseHandle(hUrlFile) ;
::InternetCloseHandle(hNet) ;
上面列舉的程式碼包括四個網路函式:InternetOpen、InternetOpenOrl、InternetReadFile和InternetCloseHandle。下面我們依次對這些函式進行分析。
InternetOpen
InternetOpen初始化WININET.DLL。它在其他的Win32網路函式之前被。
HINTERNET hNet = ::InternetOpen(
"MSDN SurfBear", // 1 LPCTSTR lpszCallerName
PRE_CONFIG_INTERNET_ACCESS, // 2 DWORD dwAccessType
"", // 3 LPCTSTR lpszName
INTERNET_INVALID_PORT_NUMBER, // 4 INTERNET_PORT nProxyPort
0 // 5 DWORD dwFlags
) ;
InternetOpen返回一個型別為HINTERNET的控制程式碼。其他的Win32網路函式把這個控制程式碼當作一個引數。現在你不能把一個HINTERNET控制程式碼用在類似於ReadFile之類的其他Win32函式中。但是隨著Microsoft Windows和Microsoft 網路支援的成熟,這一點在將來不是不可能實現的。
當你已經結束使用Wein32網路函式時,你應該呼叫InternetCloseHandle釋放InternetOpen分配的資源。使用Microsoft基礎類(MFC)的應用程式將從檔案的構造程式裡象徵性地呼叫InternetOpen。絕大多數應用程式都將在每一程式裡呼叫InternetOpen。
InternetOpen 的第一個引數lpszCallerName指定正在使用網路函式的應用程式。當使用時,這個名字將變成使用者。
第二個引數dwAccessType指定訪問型別。在上面的例子裡,PRE_CONFIG_INTERNET_ACCESS訪問型別指示Win32網路函式使用登記資訊去發現一個伺服器。使用PRE_CONFIG_INTERNET_ACCESS需要正確設定登記資訊。這裡我耍了一個小花招並讓網路開發者替我登記註冊。如果你不想欺騙,你需要按圖1所示設定登記資訊。
在登記註冊中,把AccessType設定為1,則意味著“直接入網”,把AccessType 設定為2,意味著“使用閘道器”。把DisableServiceLocation設定為1,將讓它使用一個已經命名的伺服器;否則將找到一個使用註冊資訊和名字決議(RNR)應用程式介面的伺服器,它是Windows介面的一部分。
其他的訪問型別包括以下幾種:
LOCAL_INTERNET_ACCESS只連線到當地Internet網站。例如,如果我使用SurfBear標誌,我就只能訪問Microsoft整體的Internet網站。
CERN_PROXY_INTERNET_ACCESS使用一個CERN代理去訪問。CERN代理是一個充當閘道器的web伺服器並且能向要使用代理的伺服器傳送HTTP請求。
GATEWAY_INTERNET_ACCESS允許連線到World W Web。我可以用這個訪問型別去訪問web上的任何站點。
GATEWAY_PROXY_INTERNET_ACCESS和CERN_PROXY_ACCESS訪問型別要求第三個引數給InternetOpen:伺服器名(lpszProxyName)。PRE_CONFIG_INTERNET_ACCESS不要求伺服器名,因為他可以為伺服器搜尋寄存資訊。
NProxyPort引數用在CERN_PROXY_INTERNET_ACCESS中用來指定使用的埠數。使用INTERNET_INVALID_PORT_NUMBER相當於提供卻省的埠數。
最後一個引數棗dwFlags,設定額外的選擇。你可以使用 INTERNET_FLAG_ASYNC標誌去指示使用返回句控制程式碼的將來的Internet函式將為回撥函式傳送狀態資訊,使用InternetSetStatusCallback進行此項設定。
InternetOpenUrl
一旦你把Win32網路函式初始化了,你就可以使用其他網路函式。下一個要呼叫的Internet 函式是InternetOpenUrl。這個函式連線到一個網路伺服器上並且最被從伺服器上讀取資料。InternetOpenUrl能對FTP,Gopher或HTTP協議起作用。在這篇文章中,我們只涉及HTTP協議。
HINTERNET hUrlFile = ::InternetOpenUrl(
hNet, // 1 HINTERNET hInternetSession
"", // 2 LPCTSTR lpszUrl
NULL, // 3 LPCTSTR lpszHeaders
0, // 4 DWORD dwHeadersLength
INTERNET_FLAG_RELOAD, // 5 DWORD dwFlags
0 // 6 DWORD dwContext
) ;
InternetOpenUrl也返回一個HINTERNET,它被傳遞給在這個URL(統一資源定位)上操作的函式。你應該使用InternetClose來關閉這個控制程式碼的處理。
InternetOpenUrl的第一個引數hInternetSession是從InternetOpen返回的控制程式碼。第二個引數lpszUrl是我們需要的資源的URL(統一資源定位)。在上面的例子中,我們想得到一個Microsoft的web主頁。下面兩個引數lpszHeaders和HeaderLength用來向伺服器傳送額外的資訊。使用這些引數要求具有正在使用的特定協議的知識。
DwFlag是一個可以用幾種方式修改InternetOpenUrl行為的標誌,InternetOpenUrl的行為包括關閉、隱藏,使原始資料可用和用存在的連線取代開闢一個新的連線。
最後一個引數dwContext是一個 DWORD上下文值。如果有一個值已經被指定,它將被送到狀態回撥函式。如果這個值是0,資訊將不會被送到狀態回撥函式。
InternetReadFile
你開啟一個檔案後,就要讀它,所以下一個函式是InternetReadFile是符合邏輯的:
char buffer[10*1024] ;
DWORD dwBytesRead = 0;
BOOL bRead = ::InternetReadFile(
hUrlFile, // 1 HINTERNET hFile
buffer, // 2 LPVOID lpBuffer
sizeof(buffer), // 3 DWORD dwNumberOfBytesToRead
&dwBytesRead // 4 LPDWORD lpdwNumberOfBytesRead
);
buffer[dwBytesRead] = 0 ;
pEditCtrl->SetWindowText(buffer) ;
InternetReadFile接收InternetOpenUrl返回的控制程式碼。它也對其他Win32網路函式,例如FtpOpenFile,FopherOpenFile和HttpOpenRequest返回的控制程式碼有影響。
剩下的InternetReadFile的三個引數也非常的明白直接。Inbuffer是指向保留資料的緩衝區的一個無返回值指標,dwNumberOfByteToRead以位元組為單位指定緩衝區的尺寸。最後一個引數,lpdwNumberOfBytesRead是一個指向包含讀入緩衝區位元組數的變數的指標。如果返回值是TRUE,而且lpdwNumberOfBytesRead指向0,則檔案已經讀到了檔案的末尾。這個行為與Win32 Re3adFile的函式的行為是一致的。一個真正的web瀏覽器將在InternetReadFile上迴圈 ,不停地從Internet上讀入資料塊。
為了顯示緩衝區,向緩衝區新增一個0並把它送到編輯器控制。
這樣,InternetOpen、InternetOpenUrl和InternetReadFile一起建立了Internet瀏覽器的基礎。他們使從Internet上讀取檔案就象從你的本地器上讀取檔案一樣容易。
HTTP函式
在一些例子中,InternetOpenUrl太普通了,所以你可能需要其他的Win32網路函式。InternetOpenUrl相當與不同的FTP,GOPHER和HTTP函式的封皮。當使用HTTP時,InternetOpenUrl呼叫InternetConnect,HttpOpenRequest以及HttpSendRequest,比如說我們想要在一個HTML頁之前得到它的尺寸以便於我們在緩衝區中為其分配適當的尺寸,HttpQueryInfo將得到web頁的大小。
警告:不是所有web 頁都支援得到頁尺寸。(例如:和不支援這個功能)另外,TCP/IP能傳遞的資料也比要求的要少。所以,你的應用程式應該處理著兩種情況並且圍繞InternetReadFile迴圈直到結果為TRUE同時*lpdwNumberOfBytesRead為0。
使用HttpOpenRequest,HttpSendRequest和HttpQueryInfo去開啟檔案/msdn/msdninfo的程式碼顯示如下,錯誤檢測已經被刪除。
// Open Internet session.
HINTERNET hSession = ::InternetOpen("MSDN SurfBear",
PRE_CONFIG_INTERNET_ACCESS,
NULL,
INTERNET_INVALID_PORT_NUMBER,
0) ;
// Connect to
HINTERNET hConnect = ::InternetConnect(hSession,
"",
INTERNET_INVALID_PORT_NUMBER,
"",
"",
INTERNET_SERVICE_HTTP,
0,
0) ;
// Request the file /MSDN/MSDNINFO/ from the server.
HINTERNET hHttpFile = ::HttpOpenRequest(hConnect,
"GET",
"/MSDN/MSDNINFO/",
HTTP_VERSION,
NULL,
0,
INTERNET_FLAG_DONT_CACHE,
0) ;
// Send the request.
BOOL bSendRequest = ::HttpSendRequest(hHttpFile, NULL, 0, 0, 0);
// Get the length of the file.
char bufQuery[32] ;
DWORD dwLengthBufQuery = sizeof(bufQuery);
BOOL bQuery = ::HttpQueryInfo(hHttpFile,
HTTP_QUERY_CONTENT_LENGTH,
bufQuery,
&dwLengthBufQuery) ;
// Convert length from ASCII string to a DWORD.
DWORD dwFileSize = (DWORD)atol(bufQuery) ;
// Allocate a buffer for the file.
char* buffer = new char[dwFileSize+1] ;
// Read the file into the buffer.
DWORD dwBytesRead ;
BOOL bRead = ::InternetReadFile(hHttpFile,
buffer,
dwFileSize+1,
&dwBytesRead);
// Put a zero on the end of the buffer.
buffer[dwBytesRead] = 0 ;
// Close all of the Internet handles.
::InternetCloseHandle(hHttpFile);
::InternetCloseHandle(hConnect) ;
::InternetCloseHandle(hSession) ;
// Display the file in an edit control.
pEditCtrl->SetWindowText(buffer) ;
InternetConnect
InternetConnet函式連線到一個HTTP,FTP或Gopher伺服器:
HINTERNET hConnect = ::InternetConnect(
hSession, //1 HINTERNET hInternetSession
"", //2 LPCTSTR lpszServerName
INTERNET_INVALID_PORT_NUMBER, //3 INTERNET_PORT nServerPort
"", //4 LPCTSTR lpszUsername
"", //5 LPCTSTR lpszPassword
INTERNET_SERVICE_HTTP, //6 DWORD dwService
0, //7 DWORD dwFlags
O //8 DWORD dwContext
) ;
第六個引數dwService決定服務型別(HTTP,FTP或Gopher)。在上面的例子中,InternetConnect連線到一個HTTP伺服器上,因為dwService被設定成INTERNET_SERVICE_HTTP。第二個引數(設定成)提供了伺服器的地址。注意,HTTP地址必須為伺服器名作語法分析,InternetOpenUrl為我們作語法分析。第一個引數hInternetSession是從InternetOpen返回的控制程式碼。第四個、第五個引數提供一個使用者姓名和密碼 。這七個引數沒有控制任何標誌影響HTTP操作。最後一個引數為狀態回撥函式提供前後關係的資訊。
HttpOpenRequest
一旦和伺服器的連線已經建立,我們開啟了想要的檔案。HttpOpenRequest和HttpSenRequest一起工作開啟檔案。HttpOpenRequest去建立一個請求控制程式碼並且把引數在控制程式碼中。HttpOpenRequest把請求引數送到HTTP伺服器。
HINTERNET hHttpFile = ::HttpOpenRequest(
hConnect, // 1 HINTERNET hHttpSession
"GET", // 2 LPCTSTR lpszVerb
"/MSDN/MSDNINFO/", // 3 LPCTSTR lpszName
HTTP_VERSION, // 4 LPCTSTR lpszVersion
NULL, // 5 LPCTSTR lpszReferer
0, // 6 LPCTSTR FAR * lplpszAcceptTypes
INTERNET_FLAG_DONT_CACHE, // 7 DWORD dwFlags
0 // 8 DWORD dwContext
) ;
到現在為止,網路函式的許多引數看起來都類似。HttpOpenResult的第一個引數是由InternetConnet返回的 HINTERNET。HttpOpenRequest的第七和第八個引數與InternetConnect中有相同名字的引數一樣的功能。
第二個引數(“GET”)指定我們想要得到由第三個引數(“/MSDN/MSDNINFO/”)命名的。HTTP版已經傳遞第四個引數;現在,它肯定是HTTP棗VERSION。因為“GET”是最流行的動詞型別,HttpOpenRequest將為這個引數接收一個空指標。
第五個引數lpszReferer是一個網點的地址。在這個網點上我們發現了我們現在想要看見的URL(統一資源定位)。換而言之,如果你在上而且單擊了跳到的一個連線,第五個引數就是。因為它使你指向了目標URL(統一資源定位)。這個值可以為空。第六個引數執行一個我們的程式接收的檔案型別列表。把空值傳遞給HttpOpenRequest即通知了伺服器只有文字檔案可以被接收。
HttpSendRequest
除了傳送請求外,HttpSendRequest允許你傳送額外的HTTP標題給伺服器。關於HTTP標題的資訊可以在 上的最新的說明上找到。在這個例子中,HttpSendRequest的所有引數都被傳遞為預設值。
BOOL bSendRequest = ::HttpSendRequest(
hHttpFile, // 1 HINTERNET hHttpRequest
NULL, // 2 LPCTSTR lpszHeaders
0, // 3 DWORD dwHeadersLength
0, // 4 LPVOID lpOptional
0 // 5 DWORD dwOptionalLength
);
HttpQueryInfo
為了得到關於檔案的資訊,在呼叫HttpSendRequest後使用HttpQueryInfo函式:
BOOL bQuery = ::HttpQueryInfo(
hHttpFile, // 1 HINTERNET hHttpRequest
HTTP_QUERY_CONTENT_LENGTH, // 2 DWORD dwInfoLevel
bufQuery, // 3 LPVOID lpvBuffer
&dwLengthBufQuery // 4 LPDWORD lpdwBufferLength
) ;
查詢的結構是字串或lpvBuffer中的字串列表。HTTP_QUERY_CONTENT_LENGTH查詢得到檔案的長度。你可以使用HttpQueryInfo查詢大範圍的資訊。要獲知詳細情形可查閱網點/intdev/sdk/docs/wininet上的Microsoft Win32網路函式專題。
SurfBear樣本應用程式
SurBear樣本應用程式使用Win32網路函式從Internet上得到檔案並且在編輯器上顯示原始的HTML格式。SurfBear使用HttpOpenRequest和HttpSendRequest取代InternetOpenUrl,純粹是為了演示的需要。
圖2 SurfBear 螢幕
SurfBear是一個MFC4.0版本的對話應用程式。它所有與Internet有關的功能都在InternetThread.h和InternetThread.cpp檔案中。
從internet上讀取檔案要花費相當數量的時間,所以從一個工作執行緒呼叫網路函式是一個明智的主意。透過這種方式,當在等待得到資料時,應用程式的視窗能被改變尺寸和移動。
圖3顯示了SurfBear的控制流。
當使用者按下GOTO按鈕時,CsurfBearDlg::OnBtnGoto呼叫CinternetThread:GetWebPoge,傳遞想要的web頁的HTTP地址。GetWebPage把HTTP地址語法分析成伺服器和物件名,儲存在CinternetThread的成員變數中。GetWebPage然後呼叫AfxBeginThread,它產生一個執行靜態成員函式的執行緒GetWebPage WorkerThread。如果網路函式沒有被初始化,GetWebPageWorkerThread呼叫InternetOpen,然後它嘗試讀取想要的web頁。當GetWebPageWorkerThread結束時,它傳送一個使用者定義的WM_READFILECOMPLETED訊息給SurfBear對話方塊。OnReadFileCompleted處理這個訊息並且把一個web頁複製到編輯器控制裡。
總結
Win32網路函式使從FTP,Gopher和HTTP伺服器上讀取資訊就想從你的硬碟驅動器上讀取資訊一樣容易。僅僅使用4個函式棗InternetOpen,InternetOpenUrl,InternetReadFile和InternetCloseHandle和很少的HTTP知識,你就可以寫一個簡單的網路瀏覽器。
把這個簡單的瀏覽器變成一個工業性質的瀏覽器將要花費很多工作,包括一些對HTTP的瞭解,對如何顯示HTML檔案的瞭解和以及使用多執行緒方式的能力。Win32網路函式將開發者從與TCP/IP,Windows Sockets和HTTP有關的大多數煩悶工作中解脫出來。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752043/viewspace-990600/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 網路篇—瀏覽器快取(一)瀏覽器快取
- 如何提升瀏覽器CSS的網路效能? – csswizardry瀏覽器CSS
- 神經網路啟用函式=生物轉換器?神經網路函式
- 從瀏覽器輸入一個網址開始討論網路傳輸的工作原理瀏覽器
- [譯]現代瀏覽器是如何提升效能的:網路層瀏覽器
- Socks Proxy如何讓你更安全的瀏覽網際網路
- ie瀏覽器打不開網頁怎麼辦 網路正常但是ie瀏覽器打不開解決方法瀏覽器網頁
- 利用網路請求將網路圖片轉換成Bitmap格式
- 從ReLU到GELU,一文概覽神經網路的啟用函式神經網路函式
- JS在瀏覽器中判斷當前網路狀態JS瀏覽器
- 如何建立一個瀏覽器版的`Window11`瀏覽器
- 神經網路中常用的函式神經網路函式
- 有視覺障礙,該如何瀏覽網際網路視覺
- C/C++利用Boost::Asio網路庫建立自己的Socket伺服器C++伺服器
- 網路安全趨勢一覽
- 【網路】瀏覽器輸入URL到展示頁面全過程(含網際網路協議及HTTPS簡介)瀏覽器協議HTTP
- 網路是怎樣連線的?從瀏覽器輸入URL開始瀏覽器
- 拆穿安全Web瀏覽的十大謊言,網際網路營銷Web
- 神經網路的啟用函式總結神經網路函式
- 理解神經網路的不同損失函式神經網路函式
- 神經網路中使用的啟用函式神經網路函式
- Chrome瀏覽器誕生10年,網路環境更安全更可靠了Chrome瀏覽器
- 雲伺服器基礎網路和私有網路的個人理解伺服器
- 瀏覽器渲染網頁的過程瀏覽器網頁
- 讓網際網路擁抱移動VR,三星將釋出新版VR瀏覽器VR瀏覽器
- 轉行網際網路運營是個坑
- 利用被入侵的路由器獲取網路流量路由器
- 網路分流器-網路分流器TAP網路流量分析
- 代理地址用來瀏覽網路資訊時代
- 網路分流器|網路分流器的區分
- 卷積神經網路-啟用函式卷積神經網路函式
- 如何在瀏覽器中的網路控制中快速找到傳送到後端的請求瀏覽器後端
- 神經網路簡介--啟用函式、網路架構、生物模型解釋神經網路函式架構模型
- 網路分流器|網路分流器|移動網際網路採集方案
- 自智網路:網路自身的數字化轉型
- 網路分流器-網路分流器-網路安全評估探討
- 網際網路創業怎麼起步?這個文章教你玩轉網際網路創業。創業
- 網路版“瑞士軍刀”!一個多功能的網路工具箱!
- 網路攻防原理概覽