日本免费精品_最新日韩一区_亚洲视频一区在线_a在线视频观看_天天射夜夜骑_粉嫩av一区二区三区_欧美中日韩免费视频_综合图区欧美_国内精品美女在线观看_午夜精品久久久久久久男人的天堂

首頁 > 編程 > Delphi > 正文

DELPHI與INTERNET2

2019-11-18 18:47:11
字體:
供稿:網(wǎng)友

這篇文章主要講述如何使DELPHI和因特網(wǎng)配合工作。本文中將詳述兩個專門技術:

WININET:構建 FTP,HTTP 和 Gopher 用戶端程序 ISAPI:擴充因特網(wǎng)信息服務,例如,獲得服務器上的信息并把它們顯示在瀏覽器上。

現(xiàn)今的計算機世界中,由于微軟公司的因特網(wǎng)戰(zhàn)略而掀起了一個巨大發(fā)展潮流。那些制作

CGI(公共網(wǎng)關接口)和第三方工具(即使是最基本的因特網(wǎng)工具)的日子將最終一去不復返了。對復雜的第三方工具的需求總是存在的,但現(xiàn)在程序員將會發(fā)現(xiàn)他們所需的大量的嵌入操作系統(tǒng)的因特網(wǎng)工具,簡言之,并不需要進一步的投資,你就能夠使用免費的DELPHI資源來:

*開發(fā) WEB 瀏覽器

*運行 FTP,HTTP 和 Gopher ,在兩個DELPHI應用軟件之間或DELPHI應用軟件和基于TCP

(傳輸控制協(xié)議)的服務器之間操作TCP

因為DELPHI能夠輕松地調(diào)用Windows API,并且它支持OCX/ActiveX,因此微軟的新戰(zhàn)

略和我們的計劃配合的恰到好處。微軟生產(chǎn)工具,而DELPHI程序員獲得收成!

在本篇中有些什么?

這篇文章中包含了三個大部分和一些小部分,有三個大主題:

*尋找資料:那里能搞到本文中提及的技術資料,而且包含了關于您所需的運行文中代碼 的軟硬件的簡短說明。

*ISAPI:怎樣使用ISAPI

*WININET:怎樣使用WININET

在大多數(shù)情況下,本文中的ISAPI和WININET部分是完全獨立的,您可以自由地選擇閱讀時的順序。

查找資料,硬件和軟件的要求

您需要一份Microsoft Windows NT 3.51 Server 或 NT 4.0 Server 的拷貝,其中應附有因特網(wǎng)信息服務文檔,因為您需要甬道其中所提到的技術。這份文檔應隨NT Server4.0 附送,NT 3.51的用戶可從微軟的網(wǎng)址上下載。運行Windows NT,您的機器的最低配置應為486兼容,20兆以上內(nèi)存。

您必須有另一臺計算機裝有網(wǎng)頁瀏覽器。為使本文中的ISAPI部分能夠順利運行,第二臺

機器必須能夠運行所有支持網(wǎng)頁瀏覽器的軟件。如果在您的機器上運行的是Windows 95 或 Windows NT

那么本文中的WININET 代碼片就能運行的最好。任何符合條件的網(wǎng)頁瀏覽器在這種技術環(huán)境下都能夠使用。

在1996年六月以后發(fā)布的Delphi2.0以上的版本中,有您所需的把Delphi連接到因特網(wǎng)上

的幾乎全部資源。

如果您沒有最新的Delphi版本[注:此處作者指的是2.0版本(譯者)],那么您需要本文

檔中提到的特殊文件,所有這些幾乎都可以從萬維網(wǎng)上免費獲得[注:如果您正在使用Delphi2.0以上版本,則不許考慮(譯者)]。所有本文中提到的技術在Delphi2.0環(huán)境下都能順利工作,但在16位Delphi環(huán)境下則不一定能順利工作。

如果您需要從萬維網(wǎng)上下載信息,鏈接為:http://www.borland.com/TechInfo/delphi/i

ndex.html

[注:現(xiàn)在已經(jīng)不存在了!:-(( (譯者)]

Delphi2.0的新版本中附有 WININET.PAS 文檔,如果你的拷貝中不包含它,那么上面那個

萬維網(wǎng)節(jié)點可以為您提供。WININET.PAS包括為擴展微軟視窗因特網(wǎng)所設計的變量清單、函數(shù)、類型和屬性。這意味著您能夠輕而易舉地為您的應用程序增添FTP、HTTP和Gopher支持。微軟公司的WININET.DLL是免費發(fā)布的,如果它不在您的Windows/System 或Windows/System32 目錄下的話,您可以從微軟公司那里得到它。下面是可獲得WININET.H這個視窗幫助文件的萬維網(wǎng)節(jié)點:

http://www.microsoft.com/intdev/sdk/docs/wininet/default.htm [注:好象也沒了!: -( (譯者)]

一般來說,微軟因特網(wǎng)開發(fā)者的網(wǎng)上之家是微軟節(jié)點的 INTDEV 部分。

除了WININET和ICP之外,另一個為Delphi支持的關鍵技術就是ISAP。正如微軟公司文檔中

所描述的,這項技術能使您“‘寫入’服務器端的原本和過濾本,從而擴充微軟因特網(wǎng)信息服務和其他ISAPI萬維網(wǎng)服務”。

如果您需要找到關于ISAPI的描述,可以去:

http://www.microsoft.com/intdev/sdk/servapi.htm [注:上帝保佑您!;-) (譯者)]

在本文最后,附加了一個名為HTTPEXT.PAS的關鍵的ISAPI文檔的拷貝。

微軟公司免費發(fā)布的因特網(wǎng)控制包(ICP)是一個OCX/ActiveX控制集,您可以在Delphi中

把它們拖放到應用程序上(Delphi2.0中包含這些控件)。他們提供了創(chuàng)建Delphi應用程序的即時支持,他們知道如何瀏覽網(wǎng)頁、 如何應用FTP、WINSOCK和其他因特網(wǎng)技術。如果您的Delphi拷貝中沒有包含這些控件,那么您在使用它們之前您應該把這些文檔添加進Delphi所在的目錄中的Lib目錄下。這些文檔位于上面提及的鏈接中的Borland的INDEX.HTML站點下。在本文中我沒有提到ICP控件,但是任何對這項技術有興趣的人應該明確確認他擁有這些

控件的拷貝。

您可以從我的站點下載我的Pascal應用文件,他們的名字是STRBOX.PAS 和 MATHBOX.PAS 。

經(jīng)常察看一下這個站點上的關于本文提到的信息的更新情況是很有好處的。

在這里我假設讀者對于Delphi和Object Pascal都很熟悉,并且讀者對于因特網(wǎng),HTML,

瀏覽器和萬維網(wǎng)服務器有基本的了解。

ISAPI

ISAPI是一項很容易使用然而功能強大的技術,它能夠讓您擴充因特網(wǎng)信息服務的功能。

這項技術隨WindowsNT 4.0附送,讓您在您的服務器上建立WEB、FTP和GOPHER站點。同時這項技術與WindowsNT3.51 Server[注:指服務器版本,另一個版本是工作站版本(譯者)]兼容。

在過去,擴充網(wǎng)頁服務器的最佳辦法是建立CGI應用程序。它們是強有力的工具,但是也

被他們的執(zhí)行格式所限制[注:如PERL是解釋執(zhí)行的(譯者)]。當您從瀏覽其上發(fā)出一個基于CGI的請求到服務器上時,這個CGI 應用程序?qū)O有可能先被強制裝入內(nèi)存中,這會消耗很多時間。而且,在某些環(huán)境下, CGI技術顯得稍微難用了一點。

ISAPI是一種通過寫入DLLs[注:動態(tài)鏈結程序(譯者)]從而替代CGI應用的方法。您也可

以通過ISAPI來寫過濾文本,但這項技術我不會在本篇中提及。同CGI相比,ISAPI更容易使用,而且它更快,同時能更好地利用系統(tǒng)資源。在下面幾點中,我將詳細地介紹為什么ISAPI DLLs比CGI應用要更為出色:

ISAPI DLLs與HTTP服務位于相同的地址,因此他們能夠從服務器上直接存取HTTP服務。與CGI應用相比,它們 能更快地裝入內(nèi)存;當他們在服務器上發(fā)出請求時,所需的停懸的時間[注:指發(fā)出請求到接受服務器應答的時間(譯者)]要少的多。這點當服務器的負荷很重時更加重要。

您可以控制DLLs何時被裝載和卸載。例如:您可以在第一次嘗試請求時預先裝載DLLs;當

它們不被使用時卸載 這個ISAPI應用DLLs以便釋放系統(tǒng)資源。

正如前文所述,您可以利用ISAPI寫過濾文本[注:一般指C/S結構中的腳本(譯者)],更

具微軟的文檔,您可以通過ISAPI過濾文本做下面這些事情:

用戶授權方案

壓縮

加密

登入

通信分析或其他請求分析(例如,尋找 "....etcpassWord" 中的請求)

在本文中,我會著重介紹如何編寫返回數(shù)據(jù)集的DLLs,或者是如何與運行瀏覽器的用戶進

行簡單的聯(lián)系。

ISAPI 基礎

HTTPEXT.PAS文件包含了使用ISAPI的關鍵聲明。這個文件應隨1996年6月以后發(fā)表的

Delphi版本分發(fā)。它也可以在Borland的站點上找到,在本文的ISAPI部分附有這份文檔。因為這是基于NT的技術, 您必須使用Delphi2.0以上的版本來應用這項技術。您不可能在16位的編輯器上應用它。

HTTPEXT.PAS包含了微軟公司創(chuàng)立的ISAPI技術的接口[注:指Delphi接口,ISAPI由C++編

寫(譯者)]。在編寫Delphi的時候并沒有提供ISAPI的用戶接口,我會僅僅就如何使用微軟公司的現(xiàn)有技術進行描述。不過,ISAPI 太容易使用了,而且對大多數(shù)用戶來說,用戶的Delphi對象的版本并不是必須的。

有三個函數(shù)可作為ISAPI DLLs的入口,前兩個是必須的,第三個時可選的。

GetExtensionVersion: 進對最低版本做檢查

HttpExtensionPRoc: 這是DLL的入口,就象是Delphi應用程序中的 begin...end 塊

TerminateExtension: 這是個可選的程序,它可以用作清除其他內(nèi)存分配的線程。

當您在創(chuàng)建ISAPI DLL的時候,您必須引用上面列出的三個函數(shù)中的頭兩個函數(shù),執(zhí)行這

兩個函數(shù)是所有ISAPI編程的關鍵。

這三個語句都包含了“字輸出”,使用這項術語是因為ISAPI DLLs擴充了因特網(wǎng)信息服務

器。(記住,因特網(wǎng)信息服務器指的是微軟服務器。如果您要把一臺NT服務器作為體格網(wǎng)頁服務器的話,那么,這正是您所需的工具。ISAPI DLLs隨NT4.0分發(fā),在安裝操作系統(tǒng)是自動安裝。)

ISAPI提供了一個制作服務器可遵循的標準。例如,它可以把網(wǎng)景公司的復雜的NSAPI接口

壓縮至相關的簡練而優(yōu)美的ISAPI來對NSAPI接口進行操作。

下面是這兩個重要函數(shù)的聲明

function GetExtensionVersion(var Ver: THSE_VERSION_INFO): BOOL; stdcall;

function HttpExtensionProc(var ECB: TExtensionControlBlock): DWORD; stdcall;

您只要把GetExtensionVersion粘貼到您的DLLs救行了.當ISAPI向公眾發(fā)布新版本時您只需要做輕微的改動。

function GetExtensionVersion(var Ver: THSE_VERSION_INFO):

BOOL; stdcall;

begin

Ver.dwExtensionVersion := $00010000; // 1.0 support

Ver.lpszExtensionDesc := 'Delphi 2.0 ISAPI DLL'; // Description

Result := True;

end;

The parameter passed to this function is declared in HTTPEXT.PAS as follows:

有關的參數(shù)在HTTPEXT.PAS中聲明如下:

PHSE_VERSION_INFO = ^THSE_VERSION_INFO;

THSE_VERSION_INFO = packed record

dwExtensionVersion: DWORD;

lpszExtensionDesc: array[0..HseMaxExtDLLNameLen-1] of Char;

end;

常量HseMaxExtDllNameLen 在聲明中的值為256。紀錄中的這兩個變量是“自聲明”的, 前一個包含了ISAPI的版本號[注:即變量dwExtensionVersion (譯者)],后一個則表示用戶定義的一個用來描述DLLs的字符串。

在您引用GetExtensionVersion語句的同時,您必須在您的DLL程序的DPR文件部分增添輸

出部分。在您寫這段語句時您還應該寫下:

exports

GetExtensionVersion

HttpExtensionProc;

這就是您在建立這兩個重要ISAPI DLL的函數(shù)時所要做的。下一步,使用 HttpExtensionProc,稍微復雜一點,因此我將把它作為一個獨立的部分。

與 HttpExtensionProc 一起工作

HttpExtensionProc語句是DLL的入口。它的作用就好比C語言中的 main() 語句,或者

Delphi 中的begin...end 部分

這里有一個簡單的使用GetExtensionVersion語句的例子

function HttpExtensionProc(var ECB: TExtensionControlBlock):

DWORD; stdcall;

var

ResStr: string;

StrLen: Integer;

begin

ECB.lpszLogData := 'Delphi DLL Log';

ECB.dwHTTPStatusCode := 200;

ResStr := ' +

'

Test server results

' +

'Hello from ISAPI
' +

';

ResStr := Format(

'HTTP/1.0 200 OK'#13#10+

'Content-Type: text/html'#13#10+

'Content-Length: %d'#13#10+

'Content:'#13#10#13#10'%s'

[Length(ResStr)

ResStr]);

StrLen := Length(ResStr);

ECB.WriteClient(ECB.ConnID

Pointer(ResStr)

StrLen

0);

Result := HSE_STATUS_SUCCESS;

end;

如果您在瀏覽其中向這個DLL發(fā)出請求,那么您會得到一頁這樣的回應:

Test Server Results

Hello from ISAPI

函數(shù)體內(nèi)的大部分域提供基本信息的簡單的HTML代碼密切相關。您還需要填寫TExtensionControlBlock中的一些域,如下所示。

注意到在這個紀錄里有一個叫做WriteClient的函數(shù)指針,您可以引用這個函數(shù)把信息傳

送回瀏覽器。當呼叫這個函數(shù)時,您使用到了下面提到的TExtensionControl塊中的ConnID字段。當函數(shù)被呼叫時,ConnID為您自動填充。

在察看函數(shù)的代碼之前,請讓我為您演示所有用到的上文提及的HttpExtensionProc函數(shù)

的ISAPI DLL的完整程序

library Isapi1;

library Isapi1;

uses

Windows

SysUtils

HTTPExt;

function GetExtensionVersion( var Ver: THSE_VERSION_INFO ): BOOL; stdcall;

begin

Ver.dwExtensionVersion := $00010000; // We're expecting version 1.0 support

Ver.lpszExtensionDesc := 'Written in Delphi 2.0';

Result := True;

end;

function HttpExtensionProc( var ECB: TEXTENSION_CONTROL_BLOCK ): DWORD;

stdcall;

var

ResStr: string;

StrLen: Integer;

begin

ECB.lpszLogData := 'Delphi DLL Log';

ECB.dwHTTPStatusCode := 200;

ResStr := '

' +

'

Test server results

' +

'

Isapi says hello to DevRel

';

ResStr := Format(

'HTTP/1.0 200 OK'#13#10+

'Content-Type: text/html'#13#10+

'Content-Length: %d'#13#10+

'Content:'#13#10#13#10'%s'

[Length(ResStr)

ResStr]);

StrLen := Length(ResStr);

ECB.WriteClient(ECB.ConnID

Pointer(ResStr)

StrLen

0);

Result := HSE_STATUS_SUCCESS;

end;

exports

GetExtensionVersion

HttpExtensionProc;

begin

end.

為了運行這個DLL程序,您應該把它復制到您的NT服務器下的腳本目錄中去。在我的NT4.0 機器中

它就像這樣:

c:winntsystem32inetsrvscriptsmystuffisapi1.dll

在這個例子中,我已經(jīng)創(chuàng)建了我的名為“mystuff”的目錄

它只不過是用來存儲我創(chuàng)建的

ISAPI DLLs。您的目錄,當然和我的機器上的不完全一樣,取決于您的“inetsrv”目錄位置和其它因素。

為成功調(diào)用這個DLL,您應該在您的HTML頁上增添這個超鏈接:

ISAPI One

當用戶點擊這個超鏈接時,ISAPI1 Dll會被呼叫,然后字符串“Hello from ISAPI”會顯

示在用戶的瀏覽器上。如果您并不是把 ISAPI.DLL放在 mystuff 目錄下,那么您應該修改上面的HTML代碼來使之與您的情況適應。注意,您的目錄必須與目錄 inetsrv 有關,不應,也不能包含您的整個DLL所在的目錄。

下面是呼叫的完整的HTML腳本:

My Home Page

This is the home page for my home computer.

ISAPI One

注意,如果您多次把程序ISAPI1.DLL復制到 mystuff 目錄下,在每一次復制之前您應該

關掉網(wǎng)絡服務器的萬維網(wǎng)端口。這是因為,在第一次復制這個DLL時,您可以不受限制,但在此之后,它就屬于服務器了。因此,在您復制第一次拷貝的更新版本時,因當關掉萬維網(wǎng)服務。您可以使用網(wǎng)絡管理程序來關掉萬維網(wǎng)服務。這個程序應該在微軟網(wǎng)絡管理程序組(Microsoft Internet Server group)下面,在安裝網(wǎng)絡信息服務時被安裝到程序管理器(Explorer/Program Manager)下。

與 TExtensionControlBlock 一起工作

通過本文中的這一要點,您能夠建立您的第一個ISAPI DLL,并且能在第二臺機器上的網(wǎng)

頁瀏覽器調(diào)用它。

在本文中接下來的ISAPI的其余部分將會更加深入。

這里是HttpExtensionProc參數(shù)中比較復雜的部分

PExtensionControlBlock = ^TExtensionControlBlock;

TExtensionControlBlock = packed record

cbSize: DWORD; // = sizeof(TExtensionControlBlock)

dwVersion: DWORD; // version info of this spec

ConnID: HCONN; // Context Do not modify!

dwHttpStatusCode: DWORD; // HTTP Status code

// null terminated log info specific to this Extension DLL

lpszLogData: array [0..HSE_LOG_BUFFER_LEN-1] of Char;

lpszMethod: PChar; // REQUEST_METHOD

lpszQueryString: PChar; // QUERY_STRING

lpszPathInfo: PChar; // PATH_INFO

lpszPathTranslated: PChar; // PATH_TRANSLATED

cbTotalBytes: DWORD; // Total bytes from client

cbAvailable: DWORD; // Available number of bytes

lpbData: Pointer; // pointer to cbAvailable bytes

lpszContentType: PChar; // Content type of client data

GetServerVariable: TGetServerVariableProc;

WriteClient: TWriteClientProc;

ReadClient: TReadClientProc;

ServerSupportFunction: TServerSupportFunctionProc;

end;

注意到這個紀錄中包含了上面提到過的ConnID字段,并且向 WriteClient 傳送第一個參數(shù)。

這個紀錄中的第一個參數(shù)是為版本控制而設的。它應該是TExtensionControlBlock的大小的規(guī)定。如果微軟公司改變了它的結構,那么它們能夠通過檢查紀錄的大小來判斷它們正在處理的結構版本。 您永遠也不要這個紀錄中的前三個字段,它們早已被ISAPI填充,在您的程序中,它們只能被訪問,而不能被改變。

這個紀錄中最重要的字段可能就是lpszQueryString了,它包含了從服務器上傳來的請求

的信息。例如,假設您已經(jīng)創(chuàng)建了一個名叫 ISAPI1.Dll。為了調(diào)用這個DLL,您就要在您的瀏覽器的一頁上創(chuàng)建一個像這樣的HREF [注:HTML語言中的一種格式(譯者)] :

Test One

如果您希望響應這個DLL,您就要對上面那行做這樣的改動:

Test One

假如HTML代碼段中有像上面兩行中的第二行,那么,您的DLL就會在lpszQueryString參數(shù)

中得到“MyQuery” 的字符串,特別要注意跟在請求字符串后的請求標志的使用。

當然,您可以隨心所欲地改變請求字符串。例如,您可以這樣寫:

Test One

在這個請求中,這個DLL會回答服務器的名稱。您在傳遞這個參數(shù)時,不受任何限制。您

可以傳遞任何您想要的東西,而且,如何分析DLL中的信息也由您的喜好決定。

當您從服務器返回信息至瀏覽器時,您使用到了這個紀錄中的“WriteClient”函數(shù)指針

。在初始化這個指針時您不需做任何事;它已經(jīng)自動地有網(wǎng)絡信息服務器傳遞給您了。

CGI應用程序的作者會注意到傳送請求字符串的語法十分熟悉。事實上,ISAPI跟隨了CGI

的大多數(shù)習慣,在TExtensionControlBlock中的多數(shù)字段可以簡單地被CGI技術借用。

在TExtensionControlBlock中的另一個關鍵字段是 lpbData ,它包含了從瀏覽起上傳給您的附加信息。

例如,您有一個伴隨幾個字段的HTML窗體,這些自斷中包含的信息就會被一個叫做“

lpData”的指針傳遞。本文中的下一個主題,“從‘確認’按鈕中獲得信息”,將會著重講述怎樣處理這種情況。

到現(xiàn)在為止我已經(jīng)介紹了TExtensionControlBlock中的四個關鍵字段:

WriteClient: 一個能夠讓您傳遞格式化的HTML數(shù)據(jù)到瀏覽器上的指針。這個函數(shù)用到了

TExtensionControlBlock的ConnID字段。

lpszQueryString: 從瀏覽騎上傳來的請求。

lpbData: 從瀏覽器上傳給你的人一的附加數(shù)據(jù)。通常是一個HTML窗體的任意字段的內(nèi)容

。我將在“確認 按鈕”這部分進一步討論。

要獲得其他TExtensionControlBlock中的字段是如何工作的感覺,最好的辦法就是親自在

瀏覽其中將他們做對照。換句話說,您會希望創(chuàng)建一個HTML頁,使得用能夠調(diào)用客戶端的ISAPI DLL。這個ISAPI DLL的目的僅僅是在HTML中格式話TExtensionControlBlock中的每一個字段,然后把它們傳回瀏覽器。這樣就把您的瀏覽器變成了一個有點可怕的調(diào)試器,來顯示TExtensionControlBlock中的所有字段。

這里有一個程序,由Borland公司的 Danny Thorpe 編寫,他會執(zhí)行這個任務:

library test1;

uses

Windows

SysUtils

HTTPExt;

function GetExtensionVersion( var Ver: THSE_VERSION_INFO ): BOOL; stdcall;

begin

Ver.dwExtensionVersion := $00010000; // 1.0 support

Ver.lpszExtensionDesc := 'A test DLL written in Delphi 2.0';

Result := True;

end;

function HttpExtensionProc( var ECB: TEXTENSION_CONTROL_BLOCK ):

DWORD; stdcall;

var

ResStr: string;

StrLen: Integer;

Buf: array [0..1024] of Char;

begin

ECB.lpszLogData := 'Delphi DLL Log';

ECB.dwHTTPStatusCode := 200;

ResStr := Format(

' +

'

Test server results

' +

'Size = %d
'+

'Version = %.8x
'+

'ConnID = %.8x
'+

'Method = %s
' +

'Query = %s
' +

'PathInfo = %s
'+

'PathTranslated = %s
'+

'TotalBytes = %d
'+

'AvailableBytes = %d
'+

'ContentType = %s

'+

'

Some Server Variables

'

[ECB.cbSize

ECB.dwVersion

ECB.ConnID

ECB.lpszMethod

ECB.lpszQueryString

ECB.lpszPathInfo

ECB.lpszPathTranslated

ECB.cbTotalBytes

ECB.cbAvailable

ECB.lpszContentType]);

with ECB do

begin

StrLen := Sizeof(Buf);

GetServerVariable(ConnID

'REMOTE_ADDR'

@Buf

StrLen);

ResStr := ResStr + 'REMOTE_ADDR = '+Buf+'
';

StrLen := SizeOf(Buf);

GetServerVariable(ConnID

'REMOTE_HOST'

@Buf

StrLen);

ResStr := ResStr + 'Remote_Host = '+Buf+'
';

StrLen := SizeOf(Buf);

GetServerVariable(ConnID

'REMOTE_USER'

@Buf

StrLen);

ResStr := ResStr + 'Remote_User = '+Buf+'
';

StrLen := SizeOf(Buf);

GetServerVariable(ConnID

'SERVER_NAME'

@Buf

StrLen);

ResStr := ResStr + 'SERVER_NAME = '+Buf+'
';

StrLen := SizeOf(Buf);

GetServerVariable(ConnID

'SERVER_PORT'

@Buf

StrLen);

ResStr := ResStr + 'SERVER_PORT = '+Buf+'
';

StrLen := SizeOf(Buf);

GetServerVariable(ConnID

'SERVER_PROTOCOL'

@Buf

StrLen);

ResStr := ResStr + 'SERVER_PROTOCOL = '+Buf+'
';

StrLen := SizeOf(Buf);

GetServerVariable(ConnID

'SERVER_SOFTWARE'

@Buf

StrLen);

ResStr := Format('%sSERVER_SOFTWARE = %s
'+

'ThreadID = %.8x
'

[ResStr

Buf

GetCurrentThreadID]);

end;

ResStr := ResStr + ';

ResStr := Format(

'HTTP/1.0 200 OK'#13#10+

'Content-Type: text/html'#13#10+

'Content-Length: %d'#13#10+

'Content:'#13#10#13#10'%s'

[Length(ResStr)

ResStr]);

StrLen := Length(ResStr);

ECB.WriteClient(ECB.ConnID

Pointer(ResStr)

StrLen

0);

Result := HSE_STATUS_SUCCESS;

end;

xports

GetExtensionVersion

HttpExtensionProc;

egin

end.

為了調(diào)用這個DLL,您應該建立一個包括下面這行的 HRML 腳本

Test One

從“確認”按鈕獲得信息

通常向您發(fā)送信息的HTML窗體中都有一個確認按鈕。只要信息量小于49KB,您就可以

認為TExetensionControlBlock中的 lpbData 字段是可用的。這里顯示了您可以如何在大

多數(shù)情況下獲得由這個字段的指針發(fā)來的信息:

var

S: string;

begin

S := PChar(ECB.lpbData);

end;

如果從這個字段傳來的信息大于48KB,那么您必須呼叫 ReadClient 來獲得其余的信息。

如果您想要確切地知道在 lpbData 字段中哪些信息是可用的,您可以使用下面兩個函數(shù)把數(shù)據(jù)傳回到您的網(wǎng)頁瀏覽器中:

function SetUpResString: string;

begin

Result := ' +

' +

'

Test server results

' +

'lpbData = %s ' +

';

end;

function HttpExtensionProc(var ECB: TExtensionControlBlock):

DWORD; stdcall;

var

ResStr: string;

StrLen: Integer;

S

S1: string;

begin

ECB.lpszLogData := 'Delphi DLL Log';

ECB.dwHTTPStatusCode := 200;

ResStr := SetUpResString;

S := PChar(ECB.lpbData);

ResStr := Format(ResStr

[S]);

StrLen := Length(ResStr);

ECB.WriteClient(ECB.ConnID

Pointer(ResStr)

StrLen

0);

Result := HSE_STATUS_SUCCESS;

end;

假設您已經(jīng)有了附有下面代碼的HTML窗體:

ENCTYPE="application/x-www-form-urlencoded">

Enter Number to Square:

MAXLENGTH="25" SIZE=25>

這段代碼會產(chǎn)生一個包含一個供您輸入數(shù)字的文本區(qū)和一個叫做“submit”按鈕的窗體,按鈕的名字叫做“GetSquare”。如果有了這個窗體,接著您可以預計上面的兩段程序會返回如下的字符串,假設用戶在窗體中的文本區(qū)輸入了數(shù)字23:

lpbData = GetSquare=23&GetSquare=Submit

為了理解這時究竟發(fā)生了什么,注意一下從上面函數(shù)中摘錄HTML語句中的主體部分, 這部分語句駐留在服務器上,反映如下:

'lpbData = %s ' +

如果您研究過上面 HttpExtensionProc 函數(shù)中的代碼,您會發(fā)現(xiàn)就在這句之前,它使用了 Format 語句中的 %s 參數(shù)來代替了 ECB.lpbData 中的值。(如果您不清楚語句Format 是怎樣工作的,請參閱有關的 Delphi 文檔)[注:在作者所著的 Delphi2 編程大全(Delphi2

Unleashed)中的第三章《字符串與文本文件》中有詳細說明(譯者)]

假設上面所示的窗體中,當用戶按下“確認”按鈕時,lpbData 傳遞給ISAPI DLL的值是:

GetSquare=23&GetSquare=Submit

為了讓您有清晰的概念,讓我重復一下上面兩個語句傳回給瀏覽器的信息是下面的字符串,您已經(jīng)看過了:

lpbData = GetSquare=23&GetSquare=Submit

觀看這個過程的最好辦法試運行下面列出的 ISAPI2 程序。 ISAPI2 和ISAPI1 差不多,但他包含了上面顯示的新的 HttpExtensionProc 函數(shù),并且它還包含了SetUpResString 這個實用函數(shù)。

library Isapi2;

uses

Windows

SysUtils

HTTPExt;

function GetExtensionVersion( var Ver: THSE_VERSION_INFO ):

BOOL; stdcall;

begin

Ver.dwExtensionVersion := $00010000; // 1.0 support

Ver.lpszExtensionDesc := 'DLL written in Delphi 2.0';

Result := True;

end;

function SetUpResString: string;

begin

Result := ' +

' +

'

Test server results

' +

'lpbData = %s ' +

';

end;

function HttpExtensionProc( var ECB: TEXTENSION_CONTROL_BLOCK ):

DWORD; stdcall;

var

ResStr: string;

StrLen: Integer;

S

S1: string;

Len: Integer;

begin

ECB.lpszLogData := 'Delphi DLL Log';

ECB.dwHTTPStatusCode := 200;

ResStr := SetUpResString;

S := PChar(ECB.lpbData);

ResStr := Format(ResStr

[S]);

StrLen := Length(ResStr);

ECB.WriteClient(ECB.ConnID

Pointer(ResStr)

StrLen

0);

Result := HSE_STATUS_SUCCESS;

end;

exports

GetExtensionVersion

HttpExtensionProc;

begin

end.

一旦您從窗體中獲得了由 lpbData 變量傳來的信息,您就能分析這些信息或者把它們返回給用戶。比如說,您可以從上面例子中把數(shù)字23抽出來,做平方后返回用戶。通過這樣做可以使您從用戶中獲得信息,在這里是數(shù)字,對數(shù)字進行一些數(shù)學運算,最后把結果返回給用戶。這意味著您可以在電波中創(chuàng)建互動的網(wǎng)頁,這可是現(xiàn)在因特網(wǎng)編程中最流行的哦!

以下是一個通過網(wǎng)絡提交數(shù)字平方給瀏覽器的完整的程序代碼:

library Isapi3;

{ This code shows how to take input from the user via a browser

parse that information

and then return an answer to the user. In particular

the user submits a number

this code squares it

and then sends the result back to user. Here is the form from the browser that submits the information for parsing:

ENCTYPE="application/x-www-form-urlencoded">

Enter Number to Square:

MAXLENGTH="25" SIZE=25>

}

uses

Windows

SysUtils

HTTPExt

StrBox;

function GetExtensionVersion( var Ver: THSE_VERSION_INFO ):

BOOL; stdcall;

begin

Ver.dwExtensionVersion := $00010000; // version 1.0 support

Ver.lpszExtensionDesc := 'ISAPI3.DLL';

Result := True;

end;

// Parse lpbData and retrieve the number the user passed to us.

function ParseData(S: string): Integer;

begin

S := StripLastToken(S

'&');

S := StripFirstToken(S

'=');

Result := StrToInt(S);

end;

function SetUpResString: string;

begin

Result := ' +

' +

'

Test server results

' +

'Answer = %d ' +

';

end;

function HttpExtensionProc( var ECB: TEXTENSION_CONTROL_BLOCK ):

DWORD; stdcall;

var

ResStr: string;

StrLen: Integer;

S

S1: string;

Num: Integer;

begin

ECB.lpszLogData := 'Delphi DLL Log';

ECB.dwHTTPStatusCode := 200;

ResStr := SetUpResString;

S := PChar(ECB.lpbData);

Num := ParseData(S);

Num := Sqr(Num);

ResStr := Format(ResStr

[Num]);

StrLen := Length(ResStr);

ECB.WriteClient(ECB.ConnID

Pointer(ResStr)

StrLen

0);

Result := HSE_STATUS_SUCCESS;

end;

exports

GetExtensionVersion

HttpExtensionProc;

begin

end.

這段代碼從按下確認按鈕的用戶那里接受下面的字符串,用戶要求平方后的數(shù)字:

GetSquare=5&GetSquare=Submit

假設這樣輸入,這段代碼會通過因特網(wǎng)返回用戶下面的字符串:

Answer = 25

一句話,用戶輸入數(shù)字5,你返回用戶數(shù)字25。如果用戶提交數(shù)字10,那么您返回數(shù)字100。這看起來微不足道,但在這里重要的是因特網(wǎng)上發(fā)生的行為[注:指互動網(wǎng)頁(譯

者)]

分析用戶傳來的函數(shù)像這樣:

// Parse lpbData and retrieve the number the user passed to us.

function ParseData(S: string): Integer;

begin

S := StripLastToken(S

'&');

S := StripFirstToken(S

'=');

Result := StrToInt(S);

end;

這兩個語句在單元中,在本文開頭提到過,也包含在我的站點上。[注:這個文件在網(wǎng)絡上幾乎到處可見

您也可以向譯者索取(譯者)][ 在本篇文章中

關于ISAPI我只想談這么多了。這些內(nèi)容對于啟發(fā)您利用這項優(yōu)越的技術并獲得樂趣來說應該是夠用的了。接下來我要談一下 GetServerVariable 、 ReadClient 這兩個語句,在這方面我只進行了極其有限的試驗。在本文中,我附加了HTTPEXT.PAS 文件,因為除了這分關鍵文檔,在其他地方您不會找到它。

GetServerVariable 和 ReadClient 語句

正如您的CGI應用程序中的請求信息一樣,您可以使用語句來從服務器上獲得信息。 下面是呼叫這個語句的例子:

Len := HseMaxExtDllNameLen;

SetLength(S1

Len);

Dec(Len);

ECB.GetServerVariable(ECB.ConnID

'CONTENT_LENGTH'

PChar(S1)

Len);

首先,這段代碼設定了保留從服務器上取得的信息的緩沖區(qū)的長度。接著它呼叫服務 器并發(fā)出請求,在本例中,它要求獲得服務器傳來的信息的"CONTENT_LENGTH"。

微軟公司的文獻告訴我們,您可以通過 GetServerVariable 的第二個參數(shù)來傳遞跟 著的字符串:

AUTH_TYPE 它包含了使用授權的類型。比如,如果使用的是基本(basic)授權,那么

字符串就是"basic";如果是 NT challenge 回應,字符串就是"NTLM"。其他的授權屬尤其對應的字符串。因為不斷有新的授權類型被增添到服務器上,列出所有可能的字符串是不可行的。如果字符串為空,那么并沒有使用任何授權。

CONTENT_LENGTH 腳本預計從客戶端回收到的字節(jié)數(shù)。

CONTENT_TYPE 由請求布告的主體部分提供的信息的內(nèi)容類型。[注:小弟才疏學淺,a

POST request 暫譯作"請求布告",望方家指正(譯者)]

PATH_INFO 附加的路由信息,由客戶機提供。它包含了跟在腳本名字之后的URL的漫游路

由。如果有的話,它在請求字符串的前面。

PATH_TRANSLATED 它是 PATH_INFO 的值,但包含了擴充到一個路徑標志的所有虛擬路由的名字。

QUERY_STRING 跟在參考這個腳本的URL中的"?"后面的信息。

REMOTE_ADDR 發(fā)出請求的客戶機或其代理商(例如,網(wǎng)關或防火墻)的IP地址。

REMOTE_HOST 發(fā)出請求的客戶機或其代理商(例如,網(wǎng)關或防火墻)的主機名。

REMOTE_USER 它包含了由客戶機提供并且由服務器授權的用戶名。如果返回空串那么用戶

使你名的(但是經(jīng)過授權)。

UNMAPPED_REMOTE_USER 它是有如下特征的用戶的名稱:該用戶向NT用戶帳目發(fā)出請求(這是他以身份出現(xiàn)),在此之前ISAPI應用程序過濾起映射了該用戶。

REQUEST_METHOD 是 HTTP 請求方法。

SCRIPT_NAME 執(zhí)行的腳本程序名稱。

SERVER_NAME 當它以自參考URLs形式出現(xiàn)時的主機名或IP地址。

SERVER_PORT 接受請求的TCP/IP的端口。

SERVER_PORT_SECURE 一個非0即1的字符串。當請求由安全端口處理時,它是1;否則是0 。

SERVER_PROTOCOL 接受與這個請求相關的協(xié)議的信息的名稱和版本。他通常是 HTTP/1.0 。

SERVER_SOFTWARE 是ISAPI應用DLL程序運行時所在的網(wǎng)頁服務器的名稱和版本。 ALL_HTTP 先前的變量并沒有分析全部的HTTP字段頭。這些變量從HTTP_<字段頭名>中得出 。字段頭(由行標分離)包含了各自的字符串,這些字符串并不會終止。

HTTP_ACCEPT HTTP字段頭的特例。接受的值是:字段由逗號(,)分離。例如:如果下

面的幾行是HTTP頭的一部分:

接受:*/*,q=0.1

則URL(2.0新版本的特性)給出它的基礎部分。

要注意的是,上面給出的信息片是由 TExtensionControlBlock 紀錄自動傳遞的。因

此您不需要調(diào)用GetServerVariable。不過,如果您確有需要,特別是您要從ReadClient 中獲得信息和需要知道要讀入多少信息時,您可以調(diào)用它。

在很多時候,您不需要調(diào)用 ReadClient 。但是,您瀏覽器發(fā)出的信息量大于48KB

的時候,您需要調(diào)用 ReadClient 來獲取其余的信息。


上一篇:Delphi中停靠技術的實現(xiàn)

下一篇:Delphi編寫網(wǎng)絡程序的安全措施

發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
學習交流
熱門圖片

新聞熱點

疑難解答

圖片精選

網(wǎng)友關注

精品久久久精品| 欧美日韩色综合| 国产一区在线精品| 国产乱国产乱300精品| 精品日韩在线观看| 精品欧美日韩| 欧美日韩国产成人| 亚洲尤物av| 精品在线99| 国产一区成人| 国产日产一区二区三区 | 日本亚洲视频在线| 亚洲一区在线观看网站| 国产h片在线观看| 国产绿帽一区二区三区| 国产91久久久久蜜臀青青天草二| 在线黄色国产电影| 不卡视频一区二区三区| 中文字幕视频一区二区三区久| 日韩欧美色综合| 欧美日韩在线播放三区四区| 欧美人妻一区二区三区| 高清一区二区| 亚洲v中文字幕| 中文字幕日韩欧美在线视频| 中文字幕视频在线免费欧美日韩综合在线看| 亚洲一区日韩精品中文字幕| 亚洲永久字幕| www.久久草| 国产日韩精品在线观看| 国产 欧美 在线| 91www成人久久| 国产卡1卡2卡三卡在线| 亚洲黄色片在线观看| 精品国产91乱高清在线观看| 免费高清在线一区| 日韩中文字幕在线视频观看 | 在线观看91精品国产入口| 午夜影院在线观看欧美| 国产乱国产乱老熟300部视频| 韩国一区二区av| 日韩欧美国产亚洲| 午夜亚洲一区| 二区视频在线观看| 不卡专区在线| 精品欧美日韩在线| 久久久精品日韩| 日韩视频在线一区二区| 日韩欧美在线网址| 亚洲最新永久观看在线| 午夜私人影院在线观看| 日韩 欧美 综合| 亚洲国产一区自拍| 欧美日韩在线不卡视频| 91精品日本| 交视频在线观看国产| 欧美不卡一区二区| 国产一区日韩| 在线免费视频一区二区| 亚洲欧美日本国产专区一区| 日韩欧美亚洲视频| 精品国内自产拍在线视频| 91精品无人成人www| 中文字幕亚洲二区 | 国产免费一级片| 欧美日韩高清| 精品日韩99亚洲| 伊人伊成久久人综合网小说| 色欧美日韩亚洲| 日韩wumaV| 欧美日韩中文| 免费日韩精品中文字幕视频在线| 国产成人精品日本亚洲专区61| 不卡专区在线| 国产成免费视频| 亚洲综合日韩中文字幕v在线| 国产小视频在线| 日韩中文字幕国产| 欧美日韩视频不卡| 精品欧美不卡一区二区在线观看| 国产在线导航| 国产久卡久卡久卡久卡视频精品| wwwav在线播放| 91九色在线看| 欧美日韩在线播放视频| 国产超级va在线视频| wwwav91com| 亚洲免费中文字幕| 日韩在线视频一区二区三区| 成人a在线视频免费观看| 久久久久久久久综合| 日韩欧美三级视频| 亚洲制服丝袜一区| 精品欧美日韩精品| 亚洲高清在线观看一区| 欧美 日韩 国产 在线观看| 日韩中文字幕在线一区| 亚洲视频电影在线| 日韩在线中文视频| 国产一级视频| 欧美日韩在线观看成人| 91九色在线看| 午夜精品一区二区三区视频免费看| 欧美日韩午夜在线| 激情久久99| 国产不卡在线观看视频| 久久婷婷中文字幕| 亚洲福利视频专区| 一区二区高清视频| 亚洲欧美日本另类| 国产中文在线播放| 精品一二线国产| 中文字幕日韩欧美在线| 日韩在线不卡| 欧美色视频一区二区三区在线观看| 日韩中文字幕二区| 91精品国产综合久久精品app| 日韩三级精品| 激情国产在线| 成人xxxx| 欧美日韩三级在线| 91精品啪在线观看国产60岁| 国产激情在线视频| 亚洲高清中文字幕| 欧美另类专区| 日韩高清不卡一区二区| 国产卡1卡2卡三卡在线| 亚洲三级国产| 黄色一区二区在线| 亚洲欧美日本国产专区一区| 国产日韩av高清| 日韩精品一页| 一区二区三区在线|网站| 亚洲深夜福利| 一区二区欧美国产| 日韩欧美专区在线| 欧美日韩综合在线免费观看| 日韩精品国产欧美| 国产不卡一区二区在线观看 | 在线欧美日韩精品| 日韩一级在线视频| 欧洲精品在线视频| 欧美1区免费| 中文字幕日韩在线观看| 日韩视频精品在线观看| 久久99精品久久久久久青青日本| 亚洲视频一二三四| 欧美日韩精品免费在线观看视频| 国产传媒久久久| 欧美成人精品在线| 国产黄在线看| 精品日韩视频在线观看| 日韩三级精品| 最新中文在线视频| 一级免费a一片| 亚洲成人7777| 国产日韩中文在线| 亚洲三级国产| 中文字幕在线视频日韩| 91精品国产综合久久香蕉的特点| 在线国产91| 中文字幕精品一区二区三区在线| 最新中文在线视频| 一区二区三区久久| 日韩欧美一级精品久久| 亚洲综合中文字幕在线| 中文字幕 亚洲一区| 一区二区高清在线| 91精品综合久久久久久| 久久精品夜夜夜夜久久| 国产欧美日韩在线播放| 欧美 中文字幕| 欧美国产一级片| 91精品国产自产在线| 中文字幕在线官网| 欧美日韩乱国产| 九七久久人人| 午夜国产福利在线观看| 亚洲免费精品| 国产亚洲一区字幕| 午夜精品免费视频| 国产欧美日韩在线视频| 国产福利一区二区精品秒拍| 久久精品久久精品国产大片| 国内精品99| 激情国产在线| 国产久卡久卡久卡久卡视频精品| 国产欧美久久久| 国产在线高清精品| 国产一区 二区 三区一级| 91麻豆精品国产91久久久使用方法 | 中文字幕在线欧美| 国产91久久久久蜜臀青青天草二| 久久综合九色欧美综合狠狠| √新版天堂资源在线资源| 国产一二三视频| av中文天堂在线| 欧美三级三级三级爽爽爽| 亚洲小说春色综合另类电影| wwwwww在线观看| 精品视频123区在线观看| 欧美国产一级| 日韩三级视频在线播放| 精品在线一区二区| 欧美中文字幕视频| 亚洲热在线观看| 国产在线不卡av| 欧美色欧美亚洲高清在线视频| 国产乱国产乱300精品| 一区二区视频在线观看免费的| 欧美久久久久久蜜桃| 一区二区三区久久| 日韩在线中文字幕| 日本黄色一区二区| 91麻豆视频网站| 国产v日产∨综合v精品视频| 欧美日韩国产专区| 91精品国产综合久久久久久| 中文字幕精品国产| 在线欧美一级视频| aaa大片在线观看| 日韩在线高清视频| 区日韩二区欧美三区| 亚洲永久免费视频| 欧美中文字幕在线观看视频| 日韩免费久久| 日本精品在线| 92久久精品| 色妇色综合久久夜夜| 欧美 中文字幕| 国产成人综合精品| 中文字幕一区免费| 97国产视频| 中文字幕在线观看网址| 精品国产免费视频| 亚洲免费观看在线观看| aa国产成人| 欧美日韩精品国产| 日韩精品一区二区三区视频播放| 蜜桃视频中文字幕| 国产婷婷一区二区| 国产成人精品亚洲| 欧美日韩高清一区二区不卡| 日韩欧美一卡二卡| 欧美啪啪一区| 欧美激情视频一区二区三区在线播放 | 中文在线第一页| 欧美日韩精品久久久| 色综合天天综合网国产成人综合天| 日韩专区中文字幕| 刘玥91精选国产在线观看| 日韩中文字幕在线视频观看| 91精品国产91久久| 中文字幕亚洲高清| 亚洲综合三区| 中文字幕在线官网| 国产视频一区三区| 欧美日韩国产中字 | 欧美日韩综合视频网址| 欧美日韩综合色| 国产小视频免费在线网址| 999在线视频| 欧美91精品| 福利在线国产| 国产又粗又猛又爽又黄91精品| 欧美日韩国产片| 精品国产99| 亚洲视频资源在线| 国产黄色一区| 日韩欧美中文字幕在线视频| 日韩免费精品视频| 欧美一级手机免费观看片| 中文字幕第一页在线播放| 亚洲大胆人体av| 日韩高清不卡一区二区| 久久精品久久精品亚洲人| 日韩欧中文字幕| 国产亚洲人成a一在线v站| 亚洲黄色在线观看| 91精品国产综合久久香蕉最新版| 亚洲开心激情| 在线看欧美日韩| 国产v日产∨综合v精品视频| 日韩午夜中文字幕| 欧美日韩第一| 日韩在线视频中文字幕| 91精品国产综合久久久久久| 免费日韩精品中文字幕视频在线| 黄色片免费看| 欧美日韩精品电影| 日本精品在线播放| 天天综合天天添夜夜添狠狠添| 正在播放日韩精品| 国产欧美日韩在线| 日韩中文字幕国产| 国产亚洲福利| 欧美三级一区二区三区| 精品三级在线| 亚洲一区在线观看视频| 一区二区三区在线不卡| 国产高清在线视频| 日韩一级免费视频| 成片免费观看| 欧美日韩激情一区| 一级特黄大欧美久久久| 在线国产三级| 欧美 中文字幕| 国产91久久久久蜜臀青青天草二| 国产日产一区二区三区 | 亚洲免费在线视频一区 二区| 久久91精品视频| 日韩一级精品| 一级特黄aaa大片在线观看| 日韩欧美国产视频| 欧美中文字幕精品| 91精品在线观| 国产1卡2卡三卡四卡网站| 最近高清中文在线字幕在线观看1 中文字幕在线视频久 | 日韩欧美在线1卡| av首页在线| 国产123在线| 中文字幕在线观看播放| 国产成人精品免费久久久久| 欧美日韩精品中文字幕| 国产亚洲欧美中文| 日韩中文字幕久久| 久久综合九色欧美综合狠狠| 亚洲电影中文字幕在线观看| 亚洲综合视频一区| 欧美一级免费看| 一级特黄大欧美久久久| 国产 日韩 欧美 综合| 国产一级在线| 亚洲一区三区在线观看| 亚洲a中文字幕| 精品日韩视频| 亚洲欧美999| 欧美日韩亚洲综合| 日韩高清不卡| 亚洲福利一区| 国产不卡的av| 欧美日韩亚洲91| 国产日韩专区| 1区2区在线| 久久激情一区| 欧美特黄一区| 国产视频中文字幕在线观看| 国产对白在线| 欧美日韩免费高清| 中文在线视频观看| 蜜桃视频一日韩欧美专区| 99国内精品| 日韩中文字幕在线视频播放| 91精品国产91久久久久久久久| 国产高清精品二区| 麻豆精品99| 欧美日韩第一区日日骚| 日韩免费精品| av中文在线资源| 欧美一卡2卡三卡4卡5免费| 不卡一区二区三区视频| 日韩不卡一二三区| 婷婷综合福利| 樱花草www在线观看| 国产小视频免费在线观看| 亚洲福利精品| 最近高清中文在线字幕在线观看1 中文字幕在线视频久 | 亚洲黄色www| 亚洲第一中文字幕在线观看| 国产福利第一页| 日本啊v在线| 日韩精品在线免费播放| 国产一区精品| 麻豆精品99| 亚洲欧洲在线观看av| 日韩欧美专区在线| 国产日韩综合| 日本精品国语自产拍在线观看| 国产在线不卡一区| 欧美一级久久| 在线欧美日韩精品| 精品国产999| av高清一区| 欧美久久在线| 日韩中文字幕综合| 国产乱国产乱300精品| 欧美日韩视频在线| 欧美日韩精品国产| 欧美日韩视频不卡| wwwww亚洲| 欧美成人vr18sexvr| 日韩精品一级| 欧美特黄一区| 91精品啪在线观看国产60岁| 91精品国产日韩91久久久久久| 中文字幕亚洲字幕| 亚洲免费在线视频一区 二区| 91精品国产自产| 欧美日韩综合在线| 国精品产品一区|