活动目录服务接口
China*
快速链接|微软中文主页|全球站点
Windows*
在 Microsoft.com 中搜索:
 

激活服务质量,基于Windows套接字的关键性任务应用程序

1999年5月20日 星期四



将该文档发送给同事

内容

  • 介绍
  • 集成RSVP和Diffserv
  • 定性的&定量服务质量
  • 例程
  • 相关链接

  • 介绍

    返回页首

    当前,网络消费者最关心的是执行关键任务的应用程序的服务质量(QoS),(如企业资源规划[ERP]应用程序),其次是多媒体应用程序的服务质量(QoS)。因此,Microsoft关注的焦点,迅速从单纯关注定量QoS,转向结合定性QoS,以支持ERP以及其它本质上是定性的应用程序。先前置于主机的服务质量(QoS)组件是完全模块化的,抽象的,可为定性的服务质量(QoS)容易地添加需要的支持。

    本文简要介绍主机的作用、定性的服务质量(QoS)中的应用程序、通过支持它可预期的收益以及实施提示。只需要对部分应用程序做少量的工作,就可以得到在网络服务中定性应用程序通信带来的巨大的益处了。

    服务质量(QoS)指的是一种机制的组合,它们共同为不同的网络间的应用程序的通信,提供了特定的质量。服务质量(QoS)有两个明显的好处:降低网络的时延和减少应用程序对服务质量请求的阻塞,并为网络管理员提供更高一级的控制。网络管理员可以使用不同的服务质量(QoS)机制,为不同的用户和计算机对网络资源的访问,指定优先级。服务质量机制包括:区别服务(diffserv),资源保留协议(RSVP),802.1协议,优先位标记,异步传输模式(ATM)和策略。服务质量标准化方面的工作主要在两个方面展开,RSVP和Diffserv;近来,重点是对这两种机制的集成。这个集成要以这样的方式实现-在实现其优越性的同时,保证RSVP和Diffserv服务质量是不相互排斥的,而是互补的,从而实现不同的服务质量(QoS)目标。


    集成RSVP和Diffserv

    返回页首

    主机使用RSVP,从网络的一端,向另一端发送服务质量请求信号(这通常是指点对点的服务质量)。在网络里,一些网络单元解释RSVP信令信号,其它的单元(或设备)则让它透明的传输(换而言之,没有通知)。这些设备使用信令信息,来识别哪个应用程序和用户正请求服务质量,所请求的服务类型,所请求的资源的数量。基于策略和资源的可用性,服务质量(QoS)请求会被接受或拒绝。如果请求被接受,将安装区分通信流的机制,分配适当的设备,并通知主机接受控制决定。由于为每个应用程序的通信流产生RSVP信令,随着网络的扩展,相关的联系也相应的增加,所以将可能同时存在大量的应用程序通信流。为强调这种联系,只在网络的战略节点激活RSVP,它通常在网络的最外层。

    当涉及到可扩展性时,将用到Diffserv机制。跟RSVP相反,Diffserv机制将单个的通信流组成聚集。将这些聚集作为单个的聚集流,来对它们进行服务的,减少了(在网络中的Diffserv部分)对单个流状态和单个流信令的需求。在包的IP消息头里,对它作了特定的Diffserv编码点(DSCP)标记。具有Diffserv功能的网络单元,可以使用该标记来识别该聚集流属于哪个包。当同时使用RSVP和Diffserv,RSVP被用来确定可能(或可能不会)会接受通信流的Diffserv聚集。在这个情况下,获取网络服务质量的过程中,主机的任务非常简单。产生一个RSVP请求,它将包括如下部分:

  • 请求的服务类型。
  • 所请求的资源数量。
  • 用户标识。
  • 应用程序标识。
  • 应用程序的子信息流。
  • 网络代理处理该请求,并通知主机是否接受该请求。如果接受该请求,将由网络把一个DCLASS对象发送给该主机。该对象告诉主机,将使用哪个DSCP来标识协商通信流里的包。当然,该网络自身也可以使用来自主机的请求,来标识协商流里的通信量,并在不需要对主机的进一步干涉的情况下,对包作出标识。


    定性的&定量服务质量

    返回页首

    传统的RSVP信令使用Intserv模型,以定量的方式,描述网络资源请求。这种模型适合于多媒体应用程序,如Telephony或Video,它并不适合ERP或其它定性的应用程序。要以定量的方式描述定性应用程序所需要的资源,是非常困难的。

    通过扩展到RSVP信令,并启动新的名为ServiceTypeOualitative服务类型,Microsoft提供了对定性应用程序的支持。当收到该服务类型的请求时,网络将对它作出解释(如同主机声明的一样),"不能对该通信流的请求量化,需要对此作出特殊处理。将不会含有任何定量的资源请求,但将包含应用程序名和应用程序子流的类型。在策略数据库中查找该应用程序、子流和用户,并为该通信流给出最好的优先策略。"

    在主机产生的信令中,服务类型里包含了应用程序名称和子应用程序名称。相应的,网络单元并不会将具体的资源分配给应用程序的通信流,而是给它分配特定的Diffserv聚集类。网络管理员在策略数据库中创建条目,它们指明了如何将通信流分配给不同的应用程序和不同的聚集。

    该机制使得网络管理员可以建立策略,为具体的定性应用程序的通信流指定优先级。

    定性服务质量的应用程序标准

    一些Winsock2 API(如WSAConnect和WSAAccept)始终在套接字里包含了应用程序服务质量功能。在运行Windows 2000的计算机上,(或者是低一级的Windows 98客户),这些参数将会被解释运行。具体的说,它们将触发RSVP信令,这是Diffserv机制和具体的链接层机制(如802类型的局域网里的802.1p)关联的。定量应用程序将会选择两种服务类型中的一种,并在它们对WSAConnect(或相应的)调用中,按最低限度量化它们的请求。无论是作为发送端还是接收端,这些应用程序都将以这样的方式调用服务质量(QoS)。通信流的发送端将为其发出的通信调用服务质量(QoS),接收端也将为其传入的通信调用服务质量(QoS),发送端和接收端都必须调用服务质量(QoS)。

    定性服务质量的应用程序标准

    对支持定性服务质量的最低要求,从某种意义上来说要比定量服务质量简单。它们不需要对通信量化。应用程序只需要在基本的服务质量参数中,包含所请求的服务类型SERVICETYPE_QUALITATIVE。而且,应用程序需要以发送端身份,调用服务质量。应用程序应该创建策略单元,该单元中包含了应用程序名和子应用程序名(参见下面的例码)。将会把该策略单元跟网络策略数据库中的比较,确定应该将哪个策略应用到应用程序通信中。所有其它的服务质量的功能都是自动由操作系统处理的。


    例程

    返回页首

    后面的例程(在参考下面)给出发送端的,对服务质量调用的具体代码。

    1. 创建一个策略单元,作为存储应用程序名和策略位置串的缓冲区。在参考中给出了一个策略位置串的例子。目前,还没有用以创建策略位置串的值的标准数据集。Microsoft承诺将会跟独立应用程序供应商协作,为每个需要服务质量的应用程序流,选定简单的位置串。对于选择策略位置串的唯一的要求是,相应的值必须在策略数据库中。
    2. 分配服务质量结构,并将SERVICETYPE_QUALITATIVE插入服务类型域中。用缺省的QOS_NOT_SPECIFIED值,填充余下的结构单元。
    3. 启动Winsock2提供者。
    4. 查询Winsock提供者,查找支持服务质量的服务提供者。调用该提供者,打开服务质量套接字,指定指向策略单元的服务质量结构。连接该套接字。
    5. 如果对于不同的子应用程序对应着多个流,那么,应该为每个流创建单独套接字和单独的策略。
    6. 操作系统和网络将会处理剩余部分。操作系统规定对网络请求的格式。网络响应请求,并在必要情况下,返回DCLASS对象。如果返回了DCLASS对象,操作系统将会在相应的套接字的包上作标记。

    例程说明了为获得定性服务质量,最低限度需要完成多少工作。也可以编程实现额外的功能。在该例程指向的URL中,可以找到完整的QoS API的说明书。

    参考

    普通服务质量说明书
    Winsock的FTP站点

    IETF说明书:
    定性服务类型的说明书
    结合RSVP使用的应用程序和子应用程序识别策略单元

    例程:

    /*++
    1. Use Winsock2 to find and open a QoS enabled socket.
    2. Construct a QoS structure that includes the qualitative
    service type and the corresponding provider specific buffer. The
    provider specific buffer contains a policy locator string and an
    application name string, per draft draft-bernet-appid-00.txt.
    --*/
    #include
    #include
    #include
    // WARNING: these #defines are defined here temporarily; they will be moved to QOS.H.
    #define PE_TYPE_APPID 3 // policy element contains Application Identity
    // Policy Location attribute carries sub application attributes
    #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 attribute carries the application identity
    #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 attribute structure
    typedef struct _IDPE_ATTR {
    USHORT PeAttribLength;
    UCHAR PeAttribType; // Use the #defines from above
    UCHAR PeAttribSubType; // Use the #defines from above
    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[] )
    /*+++
    Description:
    This routine creates a QoS structure, including an application identity
    policy element (PE) in the ProviderSpecific buffer. Next it opens a QoS
    socket and connects it.
    The application identity PE is suppled as part of RSVP_RESERVE_INFO
    structure. The RSVP_RESERVE_INFO is passed in as provider specific
    buffer in the WSAConnect call
    ---*/
    {
    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);
    // Set up the RSVP_RESERVE_INFO with appropriate values
    rsvp_reserve_info->Style = RSVP_FIXED_FILTER_STYLE;
    rsvp_reserve_info->ConfirmRequest = 0;
    rsvp_reserve_info->NumFlowDesc = 0;
    rsvp_reserve_info->FlowDescList = NULL;
    // ---
    // Construct the policy element that holds app id and policy locator attributes
    ConstructAppIdPe(
    szAppName,
    szPolicyLocator,
    &usRsvp_buf_len,
    (char *)rsvp_policy);
    // Set the number of Policy elements
    rsvp_reserve_info->NumPolicyElement = 1;
    // Policy elements list follows the RSVP_RESERVE_INFO structure
    rsvp_reserve_info->PolicyElementList =
    (LPRSVP_POLICY)((char *)rsvp_reserve_info + sizeof(RSVP_RESERVE_INFO));
    // Copy the application policy element into the rsvp_reserve_info->PolicyElementList
    memcpy( (char *)rsvp_reserve_info->PolicyElementList,
    (char *)rsvp_policy, rsvp_policy->Len);
    // Set the type and length of the RSVP_RESERVE_INFO finally
    rsvp_reserve_info->ObjectHdr.ObjectLength = sizeof(RSVP_RESERVE_INFO)
    + rsvp_policy->Len;
    rsvp_reserve_info->ObjectHdr.ObjectType = RSVP_OBJECT_RESERVE_INFO;

    // Fillin the QOS structure as appropriate for sender/receiver
    FillQoSStructure(Qos);
    // Supply the RSVP_RESERVE_INFO in the provider specific buffer
    Qos.ProviderSpecific.len = rsvp_reserve_info->ObjectHdr.ObjectLength;
    Qos.ProviderSpecific.buf = (char *)rsvp_reserve_info;
    Status = NO_ERROR;
    // Start up 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 {
    // Success!
    }
    }
    // ...
    return 0;
    }
    USHORT
    ConstructAppIdPe(
    IN char *szAppName,
    IN char *szPolicyLocator,
    IN OUT USHORT *pusAppIdPeBufLen,
    IN OUT char *pszAppIdPeBuf)
    /*+++
    Description:
    This routine generates the application identity PE give the name
    and policy locator strings for the application.
    The first argument szAppName is used to construct the CREDENTIAL
    attribute of the Identity PE. The subtype is set to ASCII_ID.
    The second argument szPolicyLocator is used to construct the
    POLICY_LOCATOR attribute of the Identity PE. They subtype is
    set to ASCII_DN.
    Refer to draft-ietf-rap-rsvp-identity-03.txt and draft-bernet-appid-00.txt
    for details on the Identity Policy Elements.
    Also draft-bernet-appid-00.txt conatins some examples for the
    first two arguments to this function.
    The PE is generated
    in the supplied buffer. If the length of the buffer is not
    enough required length is returned.
    Parameters: szAppName app name, string, caller supply
    szPolicyLocator Policy Locator string, caller supply
    pusAppIdPeBufLen length of caller allocated buffer
    pszAppIdPeBuf pointer to caller allocated buffer
    Return Values:
    0 Fail, pusAppIdPeBufLen will hold number of bytes needed
    > 0 Length of the application indetity 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 the supplied buffer is not long enough, return error and the
    // required buffer length
    if (*pusAppIdPeBufLen < usTotalPaddedLen) {
    *pusAppIdPeBufLen = usTotalPaddedLen;
    return 0;
    }
    memset(pszAppIdPeBuf, 0, usTotalPaddedLen);
    // Set up RSVP_POLICY header
    pAppIdPe->Len = usTotalPaddedLen;
    pAppIdPe->Type = PE_TYPE_APPID;
    // Application ID PE attributes follow the PE header
    pRsvp_pe_app_attr = (IDPE_ATTR *)(pszAppIdPeBuf + RSVP_POLICY_HDR_LEN);
    // Construct the POLICY_LOCATOR attribute with simple ASCII_DN subtype using the
    // supplied Policy Locator.
    // Since the RSVP service does not look into the
    // attributes, set the attribute length in network order.
    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);
    // Advance pRsvp_pe_app_attr
    pRsvp_pe_app_attr=(IDPE_ATTR*)(pszAppIdPeBuf+RSVP_POLICY_HDR_LEN+RSVP_BYTE_MULTIPLE(usPolicyLocatorAttrLen))
    // Construct the CREDENTIALS attribute with simple ASCII_ID subtype using the
    // supplied Application name
    // Since the RSVP service does not look into the
    // attributes, set the attribute length in network order.
    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;
    }
    // The following routine shows how to open a QoS enabled socket.
    SOCKET
    OpenQoSSocket(
    )
    {
    INT bufferSize = 0;
    INT numProtocols;
    LPWSAPROTOCOL_INFO installedProtocols, qosProtocol;
    INT i;
    SOCKET fd;
    //
    // Call WSAEnumProtocols to determine buffer size required
    //
    numProtocols = WSAEnumProtocols(NULL, NULL, &bufferSize);
    if((numProtocols != SOCKET_ERROR) && (WSAGetLastError() != WSAENOBUFS)){
    printf("Failed to enumerate protocols!\n");
    return((UINT)NULL);
    }
    else{
    //
    // Enumerate the protocols, find the QoS enabled one
    //
    installedProtocols = (LPWSAPROTOCOL_INFO)malloc(bufferSize);
    numProtocols = WSAEnumProtocols(NULL,
    (LPVOID)installedProtocols,
    &bufferSize);
    if(numProtocols == SOCKET_ERROR){
    printf("Failed to enumerate protocols!\n");
    return((UINT)NULL);
    }
    else{
    qosProtocol = installedProtocols;
    for(i=0; idwServiceFlags1 & XP1_QOS_SUPPORTED)&&
    (qosProtocol->dwServiceFlags1 & XP1_CONNECTIONLESS) &&
    (qosProtocol->iAddressFamily == AF_INET)){
    break;
    }
    qosProtocol++;
    }
    }
    //
    // Now open the socket.
    //
    fd = WSASocket(0,
    SOCK_DGRAM,
    0,
    qosProtocol,
    0,
    WSA_FLAG_OVERLAPPED);
    free(installedProtocols);
    return(fd);<
    }
    }


    相关链接

    返回页首

    FTP站点上的服务质量API的资源




    ©2006 Microsoft Corporation. 版权所有.  保留所有权利 |商标 |隐私权声明
    Microsoft