轉貼 啟用「服務品質」以 Windows Socket 為基礎的與任務密切相關的應用程式 |
|
jackkcg
站務副站長 發表:891 回覆:1050 積分:848 註冊:2002-03-23 發送簡訊給我 |
http://www.microsoft.com/taiwan/products/windows/server/technical/networking/enablingQOS.htm
啟用「服務品質」以 Windows Socket 為基礎的與任務密切相關的應用程式
今天網路客戶主要關心關鍵任務應用程式 (例如企業資源分配計畫 [ERP] 應用程式) 的「服務品質 (QoS)」,其次才是多媒體應用程式的 QoS。因此,Microsoft 改變它的開發重點,從完全定量的 QoS,到包括定質的 QoS,以支援 ERP 及其他以品質為主的應用程式。先前在主機中建立的 QoS 元件,具備足夠模組及抽象概念,可增加對定質 QoS 的支援。 本文件簡要說明主機和應用程式在定質的 QoS 中的任務、能夠具有的優點以及執行注意事項。應用程式部分只需極小的工作量,即可實現網路服務的重要優點 -- 提供定質的應用程式傳輸。 服務品質 (QoS) 是指不同機制的結合体,它在不同步網路提供特定品質的應用程式傳輸。QoS 提供兩種顯著的優點:降低對要求 QoS 的應用程式網路延遲及阻塞,並提供網路管理員更高級的控制。網路管理員可以使用不同的 QoS 機制,對不同的使用者及應用程式設定網路資源的存取優先權。QoS 機制包括「差別化服務 (diff-serv)」、「資源保留通訊協定 (RSVP)」、802.1p、優先位元標記、「非同步傳輸模式 (ATM)」及管理原則,這裡僅暫列幾個機制。兩個主要的 QoS 標準化集中在 RSVP 和 diffserv;最近則集中在這二者的整合。這項整合保留個別機制的長處,同時就個別的短處做了改進。RSVP 及 diffserv 與其他 QoS 機制不會互斥,它們可補充其他機制以達成不同的 QoS 目標。
RSVP 及 Diffserv 的整合
主機使用 RSVP 去標示從網路一端到另一端 (一般稱為端對端 QoS) 的 QoS 需求。在網路內,一些網路元素解釋 RSVP 信號,然而其他元素 (或裝置) 讓信號透明地通過 (亦即,不加注意)。這些裝置使用信號訊息去分辨要求 QoS 的應用程式與使用者、所需要的服務類型,以及所需資源的數量。基於原則及資源的可用性,QoS 的要求會被接受或拒絕。如果要求被接受,會使用機制,以分辨傳輸流、分派適當的服務,以及通知主機接受控制決定。因為對每一個應用程式傳輸流會產生 RSVP 信號,所以就同時產生大量應用程式傳輸流的網路,其網路核心的延展性值得注意。基於這些考量,RSVP 僅在策略性網路節點被啟用,通常在網路外圍。 需要延展性時,Diffserv 機制都可派上用場。跟 RSVP 相反,Diffserv 機制將單個傳輸匯總。這些匯總作為單一流,可減免在網路的 Diffserv 區段每一個流的狀態及信號的需求。封包在 IP 標題中標記特定的 Diffserv Code Point (DSCP)。Diffserv 功能的網路元素使用這個標示去分辨封包所屬的資訊流。當 RSVP 及 diffserv 一起工作,RSVP 用來檢測被接受 (或不被接受) 的 diffserv 傳輸資訊流。在這種情況下,主機在獲得網路 QoS 的工作非常容易。一個 RSVP 要求的產生包括: 要求的服務類型 要求的資源數量 使用者的身分識別 應用程式的身分識別 應用程式的子資訊流 網路代理處理這個要求並通知主機,無論這個要求是否被接受。如果這個要求被接受,一個 DCLASS 物件從網路發送到主機上。這個物件告訴主機哪一個 DSCP 用來標示傳輸資訊流中的封包。或者,網路按主機的要求處理信息資訊,以分辨資訊流上的傳輸,不用主機進一步干涉即可作出標示。
定質與定量的 QoS
傳統的 RSVP 信號使用 Intserv 模式,以定量形式表示網路資源需求。這種模式適合多媒體應用程式,例如電話傳輸或播放影像,但它並不適合 ERP 或其他定質的應用程式。定質的應用程式很難透過定量形式來判斷需要多少資源。 透過 RSVP 信號的擴充功能,Microsoft 使用一個被稱為 ServiceTypeQualitative 的新的服務類型,為定質的應用程式提供支持。當這種服務類型被要求,網路認為主機陳述:「我不知道如何去定量這個傳輸流的需求,但是它需要一些特殊的處理。我將不包括任何定量的資源需求,但是我將包括應用程式的名稱及應用程式子流的類型。在原則資料庫中查詢這個應用程式、子流及使用者,並為傳輸解析最好的優先原則。」 在主機產生的信號中,應用程式名稱及子應用程式名稱包括在服務類型中。回應時,網路元素實際上不分配特定數量的資源給應用程式的傳輸,而是指定它給一個特定的 diffserv 匯總流集類別。網路管理員在原則資料庫建立項目,並指出 (或確定) 如何去分配從不同的應用程式的傳輸流到不同的匯總流。 這種機制讓網路管理員建立傳輸特定定量應用程式優先級的原則。 定量的 Qos 的應用程式標準
幾個 Winsock2 APIs (例如 WSAConnect 及 WSAAccept) 已經在 socket 包括應用程式 QoS 性能。在 Windows 2000 電腦 (及較低程度的 Windows 98 用戶端),這些參數將被解釋及執行。它們特別引發了RSVP 信號,相關的 diffserv 機制及特定連接層級的機制 (例如 802.1p 優先級在802-style LANs之上)。定量的應用程式必須選擇兩種服務類型之一,並在它們呼叫 WSAConnect (或同類) (最低程度地) 定量它們的請求。就送件人及收件人而言,這些應用程式都需要以這種方式去呼叫 QoS。一個傳輸流的送件人將為它的外送傳輸請求 QoS,一個收件人將為進來的傳輸請求 QoS。在用戶端及伺服器 (或同級) 雙向交換 QoS 傳輸的情況時,送件人及收件人每一方都必須請求 QoS。 定質的 QoS 的應用程式標準
最小支援定質 QoS 的需求比定量的 QoS 稍微簡單。不需定量傳輸。在基本的 QoS 參數中應用程式僅僅需要包括所要求的服務類型 SERVICETYPE_QUALITATIVE。此外,應用程式作為一個送件人需要請求 QoS (不是作為一個收件人)。應用程式將建立一個原則元素 (參考下面的範例程式碼),它包括應用程式名稱及子應用程式名稱。原則元素與網路的原則資料庫作比較以檢測哪一個原則適用於應用程式傳輸。全部其他的 QoS 功能被作業系統自動處理。
字碼範例
接下來的字碼範例 (下面引用的) 說明了送件人對 Qos 的呼叫。 將原則元素構造為一個提供程式特性緩衝區,內含應用程式名稱及原則定位字串。在引用設計中提供了一個原則定位字串的範例。目前,還沒有可用來構造原則定位字串的標準數值集。Microsoft 承諾與獨立應用程式供應商一道為每一個需要 QoS 的應用程式流選取一個簡單的原則定位字串。選擇原則定位字串的唯一需求是相對應的數值必須存在於原則資料庫中。 分配一個 QoS 結構並將 SERVICETYPE_QUALITATIVE 插入服務類型欄。使用預設的 QOS_NOT_SPECIFIED 數值填入剩下的結構元素。
啟動 Winsock2 提供程式。 查詢 Winsock 提供程式以尋找 QoS功能的服務提供者 (SP)。呼叫提供程式去開啟一個 QoS 通訊端,指出指向原則元素的 QoS 結構。連接通訊端。
如果不同的子應用程式對應不同的流,應為每個流單獨建立通訊端及原則元素。 剩下的事交給作業系統及網路。作業系統要求網路一定的格式。網路執行這一要求,如有必要就傳回一個 DCLASS 物件。如果傳回 DCLASS 物件,OS 就為通訊端上的封包作標示。 這個字碼範例表現了為獲得定質的 QoS 所需的最少的工作。也可編寫附加功能的字碼。關於 QoS API 的完整說明可從字碼範例中引用的 URL 上得到。附加的功能 (未包含在範例中) 是 QoS 事件監視能力;亦即,送件人及收件人可以用來監視 QoS 事件,接收網路認可或拒絕 QoS 要求的通知。 參照
標準的 QoS 說明:
FTP Winsock 站台 IETF 說明:
關於定質服務類型的說明
使用 RSVP 信號的 DCLASS 物件的格式及使用方式
搭配 RSVP 使用的應用程式及子應用程式中身分識別原則元素 字碼範例:
/*
1. 使用 Winsock2 搜尋及開啟一個 QoS 型通訊端。
2. 構造一個定質的 QoS 結構
服務類型及相對應的提供程式特性的緩衝區。
提供程式特性緩衝區內包含一個原則定位字串及一個
應用程式名稱字串,根據草稿:draft-bernet-appid-00.txt。
--*/
#include
#include
#include
// WARNING:這些 #defines 在這裡臨時定義;它們將被移至 QOS.H。
#define PE_TYPE_APPID 3 // 原則元素內含「應用程式身分識別 (Application Identity)」
// 「原則定位 (Policy Location)」屬性包含子應用程式的屬性
#define PE_ATTRIB_POLICY_LOCATOR 1
#define POLICY_LOCATOR_SUB_TYPE_ASCII_DN 1
#define POLICY_LOCATOR_SUB_TYPE_UNICODE_DN 2
#define POLICY_LOCATOR_SUB_TYPE_ASCII_DN_ENC 3
#define POLICY_LOCATOR_SUB_TYPE_UNICODE_DN_ENC 4 // 「憑證 (Credentials)」屬性包含應用程式的特性識別
#define PE_ATTRIB_CREDENTIAL 2
#define CREDENTIAL_SUB_TYPE_ASCII_ID 1
#define CREDENTIAL_SUB_TYPE_UNICODE_ID 2
#define CREDENTIAL_SUB_TYPE_KERBEROS_TKT 3
#define CREDENTIAL_SUB_TYPE_X509_V3_CERT 4
#define CREDENTIAL_SUB_TYPE_PGP_CERT 5 // 「身分識別原則元素 (Identity Policy Element)」屬性結構
typedef struct _IDPE_ATTR {
USHORT PeAttribLength;
UCHAR PeAttribType; // 使用上文的 #defines
UCHAR PeAttribSubType; // 使用上文的 #defines
UCHAR PeAttribValue[4];
} IDPE_ATTR, *LPIDPE_ATTR;
#define IDPE_ATTR_HDR_LEN (sizeof(USHORT) sizeof(UCHAR) sizeof(UCHAR))
#define RSVP_BYTE_MULTIPLE(x) (((x / 4) 1) * 4)
#define RSVP_BUF_LEN 1024
#define VERSION MAKEWORD( 2,2 )
USHORT
ConstructAppIdPe(
IN char *szAppName,
IN char *szPolicyLocatorDn,
IN OUT USHORT *pusAppIdPeBufLen,
IN char *pszAppIdPeBuf);
VOID
FillQoSStructure(
IN QOS Qos);
SOCKET
OpenQoSSocket();
_cdecl
main(
int argc,
char *argv[] )
/*
具體表述:
該常式建立一個 QoS 結構,其中包含位於
ProviderSpecific 緩衝區中的應用程式身分識別原則元素 (PE)。下一步開啟一個 QoS
通訊端並進行連接。
應用程式身分識別 (PE) 被納入為RSVP_RESERVE_INFO 結構
中的一部分。SVP_RESERVE_INFO 作為
WSAConnect 呼叫中的提供程式特性緩衝區被傳送進來。
---*/
{
int Status;
DWORD dwError;
UCHAR szAppName[40];
UCHAR szPolicyLocator[40];
USHORT usRsvp_buf_len = RSVP_BUF_LEN;
char rsvp_buf[RSVP_BUF_LEN];
char ps_buf[RSVP_BUF_LEN];
struct sockaddr RemoteHost;
SOCKET Socket;
QOS Qos;
WSADATA WsaData;
RSVP_RESERVE_INFO *rsvp_reserve_info = (RSVP_RESERVE_INFO *)&ps_buf;
RSVP_POLICY *rsvp_policy = (RSVP_POLICY *)&rsvp_buf;
memset(ps_buf, 0, RSVP_BUF_LEN);
memset(rsvp_buf, 0, RSVP_BUF_LEN);
// 用適當的數值設定 RSVP_RESERVE_INFO
rsvp_reserve_info->Style = RSVP_FIXED_FILTER_STYLE;
rsvp_reserve_info->ConfirmRequest = 0;
rsvp_reserve_info->NumFlowDesc = 0;
rsvp_reserve_info->FlowDescList = NULL;
// ---
// 構造包含應用程式 ID 及原則定位屬性的原則元素
ConstructAppIdPe(
szAppName,
szPolicyLocator,
&usRsvp_buf_len,
(char *)rsvp_policy);
// 設定「原則 (Policy)」元素的數字
rsvp_reserve_info->NumPolicyElement = 1;
// 原則元素清單在 RSVP_RESERVE_INFO 結構之後列出來
rsvp_reserve_info->PolicyElementList =
(LPRSVP_POLICY)((char *)rsvp_reserve_info sizeof(RSVP_RESERVE_INFO));
// 將應用程式原則元素複製到 rsvp_reserve_info->PolicyElementList
memcpy( (char *)rsvp_reserve_info->PolicyElementList,
(char *)rsvp_policy,
rsvp_policy->Len);
// 設定 RSVP_RESERVE_INFO 最終的類型及長度
rsvp_reserve_info->ObjectHdr.ObjectLength = sizeof(RSVP_RESERVE_INFO)
rsvp_policy->Len;
rsvp_reserve_info->ObjectHdr.ObjectType = RSVP_OBJECT_RESERVE_INFO; // 為送件人、收見人的需要適當填入 QOS 結構
FillQoSStructure(Qos);
// 在提供程式特性緩衝區中提供 RSVP_RESERVE_INFO
Qos.ProviderSpecific.len = rsvp_reserve_info->ObjectHdr.ObjectLength;
Qos.ProviderSpecific.buf = (char *)rsvp_reserve_info;
Status = NO_ERROR;
// 啟動 Winsock 2
Status = WSAStartup( VERSION, &WsaData );
if (Status != NO_ERROR ) {
exit(-1);
}
Socket = OpenQoSSocket();
if((Socket == (UINT)NULL) || Socket == INVALID_SOCKET)){
// Error handling
}
else {
Status = WSAConnect( Socket,
(struct sockaddr *)&RemoteHost,
sizeof( struct sockaddr_in ),
NULL,
NULL,
&Qos,
NULL );
if (Status != NO_ERROR ) {
// Error handling
}
else {
// 成功!
}
}
// ...
return 0;
}
USHORT
ConstructAppIdPe(
IN char *szAppName,
IN char *szPolicyLocator,
IN OUT USHORT *pusAppIdPeBufLen,
IN OUT char *pszAppIdPeBuf)
/*
具體表述:
這個常式產生應用程式身分識別 PE,
給與應用程式名稱及原則定位字串
第一個引數 szAppName 用來構造身分識別 PE 的
CREDENTIAL 屬性。子類型設定為 ASCII_ID。
第二個引數 szPolicyLocator 用來構造
「身分識別 (Identity)」PE 的 POLICY_LOCATOR 屬性。子類型
設定為 ASCII_DN。
請參閱 draft-ietf-rap-rsvp-identity-03.txt 及 draft-bernet-appid-00.txt
以獲取關於 Identity Policy Elements 的詳細資料。
draft-bernet-appid-00.txt 中還包含一些關於
這個函數前兩個引數的範例。
PE 產生
於所提供的緩衝區中。如果緩衝區長度不足,
則傳回必需的長度
參數:szAppName 應用程式名稱,字串,呼叫程式提供
szPolicyLocator Policy Locator 字串,呼叫程式提供
pusAppIdPeBufLen 呼叫程式分配的緩衝區長度
pszAppIdPeBuf 指向呼叫程式分配的緩衝區的指標
Return Values:
0 失敗,pusAppIdPeBufLen 中保留所需的位元組數目
> 0 應用程式身份識別 PE 的長度
---*/
{
RSVP_POLICY *pAppIdPe = (RSVP_POLICY *)pszAppIdPeBuf;
IDPE_ATTR *pRsvp_pe_app_attr;
USHORT usAppIdAttrLen;
USHORT usPolicyLocatorAttrLen;
USHORT usTotalPaddedLen;
if ( !szAppName
|| !szPolicyLocator )
return 0;
usPolicyLocatorAttrLen = IDPE_ATTR_HDR_LEN strlen(szPolicyLocator);
usAppIdAttrLen = IDPE_ATTR_HDR_LEN strlen(szAppName);
// Calculcate the length of the buffer required
usTotalPaddedLen = RSVP_POLICY_HDR_LEN
RSVP_BYTE_MULTIPLE(usAppIdAttrLen)
RSVP_BYTE_MULTIPLE(usPolicyLocatorAttrLen);
// 如果提供的緩衝區長度不足,傳回錯誤及
// 必需的緩衝區長度
if (*pusAppIdPeBufLen < usTotalPaddedLen) {
*pusAppIdPeBufLen = usTotalPaddedLen;
return 0;
}
memset(pszAppIdPeBuf, 0, usTotalPaddedLen);
// 設定 RSVP_POLICY 的標題
pAppIdPe->Len = usTotalPaddedLen;
pAppIdPe->Type = PE_TYPE_APPID;
// 應用程式 ID PE 屬性緊隨 PE 標題之後
pRsvp_pe_app_attr = (IDPE_ATTR *)(pszAppIdPeBuf RSVP_POLICY_HDR_LEN);
// 用簡單的 ASCII_DN 子類型構造 POLICY_LOCATOR 屬性,使用
// 某「原則定位器」。
// 因為 RSVP 服務不檢查
// 這些屬性,所以依網路順序設定屬性長度。
pRsvp_pe_app_attr->PeAttribLength = htons(usPolicyLocatorAttrLen);
pRsvp_pe_app_attr->PeAttribType = PE_ATTRIB_POLICY_LOCATOR;
pRsvp_pe_app_attr->PeAttribSubType = POLICY_LOCATOR_SUB_TYPE_ASCII_DN;
strcpy((char *)pRsvp_pe_app_attr->PeAttribValue, szPolicyLocator);
// 高級的 pRsvp_pe_app_attr
pRsvp_pe_app_attr=(IDPE_ATTR*)(pszAppIdPeBuf RSVP_POLICY_HDR_LEN RSVP_BYTE_MULTIPLE(usPolicyLocatorAttrLen))
// 用簡單的 ASCII_ID 子類型構造 CREDENTIALS 屬性,使用
// 給定的「應用程式 (Application)」名稱
// 因為 RSVP 服務不檢查
// 這些屬性,所以依網路順序設定屬性長度。
pRsvp_pe_app_attr->PeAttribLength = htons(usAppIdAttrLen);
pRsvp_pe_app_attr->PeAttribType = PE_ATTRIB_CREDENTIAL;
pRsvp_pe_app_attr->PeAttribSubType = CREDENTIAL_SUB_TYPE_ASCII_ID;
strcpy((char *)pRsvp_pe_app_attr->PeAttribValue, szAppName);
return usTotalPaddedLen;
}
VOID
FillQoSStructure(
QOS Qos
)
{
LPFLOWSPEC flowSpec;
flowSpec = &Qos.SendingFlowspec;
flowSpec->TokenRate = QOS_NOT_SPECIFIED;
flowSpec->TokenBucketSize = QOS_NOT_SPECIFIED;
flowSpec->PeakBandwidth = QOS_NOT_SPECIFIED;
flowSpec->Latency = QOS_NOT_SPECIFIED;
flowSpec->DelayVariation = QOS_NOT_SPECIFIED;
flowSpec->ServiceType = SERVICETYPE_QUALITATIVE;
flowSpec->MaxSduSize = QOS_NOT_SPECIFIED;
flowSpec->MinimumPolicedSize = QOS_NOT_SPECIFIED;
}
// 下列常式顯示如何開啟一個 QoS 功能的通訊端。
SOCKET
OpenQoSSocket(
)
{
INT bufferSize = 0;
INT numProtocols;
LPWSAPROTOCOL_INFO installedProtocols, qosProtocol;
INT i;
SOCKET fd;
//
// 呼叫 WSAEnumProtocols,以確定需要的緩衝區大小
//
numProtocols = WSAEnumProtocols(NULL, NULL, &bufferSize);
if((numProtocols != SOCKET_ERROR) && (WSAGetLastError() != WSAENOBUFS)){
printf("列舉通訊協定失敗!\n");
return((UINT)NULL);
}
else{
//
// 列舉通訊協定,尋找一個啟用的 QoS
//
installedProtocols = (LPWSAPROTOCOL_INFO)malloc(bufferSize);
numProtocols = WSAEnumProtocols(NULL,
(LPVOID)installedProtocols,
&bufferSize);
if(numProtocols == SOCKET_ERROR){
printf("列舉通訊協定失敗!\n");
return((UINT)NULL);
}
else{
qosProtocol = installedProtocols;
for(i=0; idwServiceFlags1 & XP1_QOS_SUPPORTED)&&
(qosProtocol->dwServiceFlags1 & XP1_CONNECTIONLESS) &&
(qosProtocol->iAddressFamily == AF_INET)){
break;
}
qosProtocol ;
}
}
//
// 現在,開啟通訊端。
//
fd = WSASocket(0,
SOCK_DGRAM,
0,
qosProtocol,
0,
WSA_FLAG_OVERLAPPED);
free(installedProtocols);
return(fd);<
}
}
------
********************************************************** 哈哈&兵燹 最會的2大絕招 這個不會與那個也不會 哈哈哈 粉好 Delphi K.Top的K.Top分兩個字解釋Top代表尖端的意思,希望本討論區能提供Delphi的尖端新知 K.表Knowlege 知識,就是本站的標語:Open our mind |
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |