⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 qosmcast.c

📁 《Windows网络编程技术》附书源码源码. 运行环境:9x/Me/NT/2000/XP/ 源码语言:简体中文 第十二章
💻 C
📖 第 1 页 / 共 2 页
字号:
// Module Name: qosmcast.c
//
// Description:
//    This sample illustrates multicasting with QOS. QOS may be
//    set before calling WSAJoinLeaf, during WSAJoinLeaf, after
//    WSAJoinLeaf, or QOS may be set when an FD_QOS event has been
//    received. This sample acts as wither a sender or receiver. 
//    In both cases, the multicast group is joined. Multiple 
//    groups may be joined by specifying one or more -m:IP
//    options.
//  
// Compile:
//    cl qosmcast.c provider.c printqos.c ws2_32.lib
//
// Command Line Parameters/Options
//    qosmcast.exe -q:x -s -r -m:IP-addr
//        -q:[b,d,a,e]    When to request QOS
//            b           Set QOS before bind or connect
//            d           Set QOS during accept cond func
//            a           Set QOS after session setup
//            e           Set QOS only upon receipt of FD_QOS
//        -s              Act as sender
//        -r:IP           Act as receiver
//        -w              Wait to send until RESV has arrived
//        -m:addr         Multicast address to join
//        -c              Confirm reservation request
//
#include <winsock2.h>
#include <windows.h>

#include <qos.h>
#include <qossp.h>

#include "provider.h"
#include "printqos.h"

#include <stdio.h>
#include <stdlib.h>

#define QOS_BUFFER_SZ       32000      // Default buffer size for SIO_GET_QOS
#define DATA_BUFFER_SZ       2048      // Send/Recv buffer size

#define MAX_MULTICAST_GROUPS   32
#define MAX_RECEIVERS          32

#define SET_QOS_NONE          0      // No QOS
#define SET_QOS_BEFORE        1      // Set QOS on listening socket
#define SET_QOS_DURING        2      // Set QOS during conditional accept
#define SET_QOS_AFTER         3      // Set QOS after accept completed
#define SET_QOS_EVENT         4      // Wait for FD_QOS before setting

int   iSetQos,                       // When to set qos
      iNumGroups,                    // Number of groups to join
      iNumSenders;
      iFlowStyle=RSVP_DEFAULT_STYLE; // Style
char  szMulticastAddrs[MAX_MULTICAST_GROUPS][64],
      szSenderAddrs[MAX_RECEIVERS][64];
BOOL  bSender,                       // Sending or receiving?
      bWaitToSend,                   // Wait for confirmation before sending?
      bConfirmResv;
QOS   sendQos,                       // Sender's QOS values
      recvQos;                       // Receiver's QOS values

RSVP_RESERVE_INFO  qosreserve;             // use to set filter style
FLOWDESCRIPTOR     flow[MAX_RECEIVERS];
RSVP_FILTERSPEC    filters[MAX_RECEIVERS];

//
// Setup some common FLOWSPECS
//
const FLOWSPEC flowspec_notraffic = {QOS_NOT_SPECIFIED,
                                     QOS_NOT_SPECIFIED,
                                     QOS_NOT_SPECIFIED,
                                     QOS_NOT_SPECIFIED,
                                     QOS_NOT_SPECIFIED,
                                     SERVICETYPE_NOTRAFFIC,
                                     QOS_NOT_SPECIFIED,
                                     QOS_NOT_SPECIFIED};

const FLOWSPEC flowspec_g711 = {8500,
                                680,
                                17000,
                                QOS_NOT_SPECIFIED,
                                QOS_NOT_SPECIFIED,
                                SERVICETYPE_CONTROLLEDLOAD,
                                340,
                                340};

//
// Function: usage
//
// Description:
//    Print out usage information.
//
void usage(char *progname)
{
    printf("usage: %s -q:x -s -r[:IP] -m:IP-addr\n", progname);
    printf("      -q:[b,d,a,e]    When to request QOS\n");
    printf("          b           Set QOS before bind or connect\n");
    printf("          d           Set QOS during accept cond func\n");
    printf("          a           Set QOS after session setup\n");
    printf("          e           Set QOS only upon receipt of FD_QOS\n");
    printf("      -s              Act as sender\n");
    printf("      -r[:IP]         Act as receiver\n");
    printf("      -w              Wait to send until RESV has arrived\n");
    printf("      -m:addr         Multicast address to join\n");
    printf("      -f:[se:ff]      Filter style\n");
    printf("          se          Shared explicit style\n");
    printf("          ff          (Multiple) Fixed filter style\n");
    printf("      -c              Confirm reservation request\n");
    ExitProcess(-1);
}

// 
// Function: InitQos
//
// Description:
//    Initalize the sending and receiving QOS structures for use in
//    setting QOS on a socket. Also use the RSVP_RESERVE_INFO object
//    to request confirmation of the reservation request (which is
//    only valid for the receiver since it's the receiver who
//    generates the RESV statement).
//
void InitQos()
{
    sendQos.SendingFlowspec = flowspec_g711;
    sendQos.ReceivingFlowspec =  flowspec_notraffic;
    sendQos.ProviderSpecific.buf = NULL;
    sendQos.ProviderSpecific.len = 0;

    recvQos.SendingFlowspec = flowspec_notraffic;
    recvQos.ReceivingFlowspec = flowspec_g711;
    recvQos.ProviderSpecific.buf = NULL;
    recvQos.ProviderSpecific.len = 0;
}

// 
// Function: ValidateArgs
//
// Description:
//    Parse command line arguments and set global variables to
//    indicate how the application should act.
//
void ValidateArgs(int argc, char **argv)
{
    char    *ptr=NULL;
    int      i;

    // Initialize globals to a default value
    //
    iSetQos = SET_QOS_NONE;
    iNumGroups = 0;
    iNumSenders = 0;
    bSender = TRUE;
    bWaitToSend = FALSE;
    bConfirmResv = FALSE;

    for(i=1; i < argc ;i++)
    {
        if ((argv[i][0] == '-') || (argv[i][0] == '/'))
        {
            switch (tolower(argv[i][1]))
            {
                case 'q':        // When to set QOS
                    if (tolower(argv[i][3]) == 'b')
                        iSetQos = SET_QOS_BEFORE;
                    else if (tolower(argv[i][3]) == 'd')
                        iSetQos = SET_QOS_DURING;
                    else if (tolower(argv[i][3]) == 'a')
                        iSetQos = SET_QOS_AFTER;
                    else if (tolower(argv[i][3]) == 'e')
                        iSetQos = SET_QOS_EVENT;
                    else
                        usage(argv[0]);
                    break;
                case 's':        // sender
                    bSender = TRUE;
                    break;
                case 'r':        // receiver
                    bSender = FALSE;
                    if (strlen(argv[i]) > 3)
                        strcpy(szSenderAddrs[iNumSenders++], &argv[i][3]);
                    break;
                case 'm':        // the multicast address to join
                    if (strlen(argv[i]) > 3)
                        strcpy(szMulticastAddrs[iNumGroups++], &argv[i][3]);
                    else
                        usage(argv[0]);
                    break;
                case 'w':       // wait to send data until
                                // RESV has arrived
                    bWaitToSend = TRUE;
                    break;
                case 'f':       // Filter style
                    ptr = &argv[i][3];
                    while (*ptr)  
                        *ptr++ = tolower(*ptr);
                    if (!strncmp("ff", &argv[i][3], 2))
                        iFlowStyle = RSVP_FIXED_FILTER_STYLE;
                    else if (!strncmp("se", &argv[i][3], 2))
                        iFlowStyle = RSVP_SHARED_EXPLICIT_STYLE;
                    else
                        usage(argv[0]);
                    break;
                case 'c':       // Confirm reservation
                    bConfirmResv = TRUE;
                    break;
                default:
                    usage(argv[0]);
                    break;
            }
        }
    }
    return;
}

//
// Function: SetQosReserveInfo
//
// Description:
//    This function simply fills out the RSVP_RESERV_INFO object
//    with the requested style and sets the RSVPFLOWDESCRIPTOR
//    and RSVP_FILTERSPEC with the sender's addresses according
//    to the selected filter style.
//
void SetQosReserveInfo(QOS *lpqos)
{
    DWORD  dwSize=0;
    int    i, j;

    memset(&qosreserve, 0, sizeof(qosreserve));
    //
    // Initialize the RSVP_RESERVE_INFO structure
    //
    qosreserve.ObjectHdr.ObjectType = RSVP_OBJECT_RESERVE_INFO;
    qosreserve.ObjectHdr.ObjectLength = sizeof(RSVP_RESERVE_INFO);
    qosreserve.Style = iFlowStyle;
    qosreserve.ConfirmRequest = bConfirmResv;
    qosreserve.NumPolicyElement  = 0;
    qosreserve.PolicyElementList = NULL;
    qosreserve.FlowDescList = flow;
    
    if (iFlowStyle == RSVP_SHARED_EXPLICIT_STYLE)
    {
        // For shared explicit there is one FLOWSPEC for all
        // senders.
        //
        qosreserve.NumFlowDesc = 1;

        flow[0].FlowSpec = lpqos->ReceivingFlowspec; 
        flow[0].NumFilters = iNumSenders;
        flow[0].FilterList = filters;

        for(i=0; i < iNumSenders ;i++) 
        {
            filters[i].Type = FILTERSPECV4;
            filters[i].FilterSpecV4.Address.Addr = inet_addr(szSenderAddrs[i]);
            filters[i].FilterSpecV4.Port = htons(5150);
        }
    }
    else
    {
        // For multiple fixed filter there is one FLOWSPEC for
        // each sender. This means that each RSVPFLOWDESCRIPTOR
        // references a single FLOWSPEC and a single RSVP_FILTERSPEC.
        //
        qosreserve.NumFlowDesc = iNumSenders;
        
        j=0;
        for(i=0; i < iNumSenders ;i++)
        {
            flow[i].FlowSpec = lpqos->ReceivingFlowspec;
            flow[i].NumFilters = 1;
            flow[i].FilterList = &filters[j];
        
            filters[j].Type = FILTERSPECV4;
            filters[j].FilterSpecV4.Address.Addr = inet_addr(szSenderAddrs[j]);
            filters[j].FilterSpecV4.Port = htons(5150);
            j++;
        }
    }
    lpqos->ProviderSpecific.buf = (char *)&qosreserve;
    lpqos->ProviderSpecific.len = sizeof(RSVP_RESERVE_INFO);

    return;
}

//
// Function: SetQosReceivers
//
// Description:
//    This function sets the RSVP_RESERVE_INFO provider specific
//    object if a different filter has been specified along with
//    the sender's IP address. It then calls SIO_SET_QOS to set
//    the supplied QOS parameters on the socket.
//
BOOL SetQosReceivers(SOCKET s, QOS *lpqos)
{
    int       ret;
    DWORD     dwBytes,
              dwSize;

    if (iNumSenders > 0)
    {
        SetQosReserveInfo(lpqos);
        dwSize = sizeof(QOS) + sizeof(RSVP_RESERVE_INFO);
    }
    else
    {
        lpqos->ProviderSpecific.buf = NULL;
        lpqos->ProviderSpecific.len = 0;

        dwSize = sizeof(QOS);
    }
    PrintQos(lpqos);

    ret = WSAIoctl(s, SIO_SET_QOS, lpqos, dwSize, NULL, 0, 
        &dwBytes, NULL, NULL);
    if (ret == SOCKET_ERROR)
    {
        printf("WSAIoctl(SIO_SET_QOS) failed: %d\n",
            WSAGetLastError());
        return FALSE;
    }
    return TRUE;
}

//
// Function: ChkForQosStatus
//
// Description:
//    Check for the presence of a RSVP_STATUS_INFO object and
//    determine if the supplied flags are present in that
//    object.
//
DWORD ChkForQosStatus(QOS *lpqos, DWORD dwFlags)
{
    QOS_OBJECT_HDR   *objhdr= NULL;
    RSVP_STATUS_INFO *status=NULL;
    char             *bufptr= NULL;
    BOOL              bDone = FALSE;
    DWORD             objcount = 0;

    if (lpqos->ProviderSpecific.len == 0)
        return 0;

    bufptr = lpqos->ProviderSpecific.buf;
    objhdr = (QOS_OBJECT_HDR *)bufptr;


    while (!bDone)
    {
        if (objhdr->ObjectType == RSVP_OBJECT_STATUS_INFO)
        {
            status = (RSVP_STATUS_INFO *)objhdr;
            if (status->StatusCode & dwFlags)
                return 1;
        }
        else if (objhdr->ObjectType == QOS_OBJECT_END_OF_LIST)
            bDone = TRUE;

        bufptr += objhdr->ObjectLength;
        objcount += objhdr->ObjectLength;
        objhdr = (QOS_OBJECT_HDR *)bufptr;

        if (objcount >= lpqos->ProviderSpecific.len)
            bDone = TRUE;
    }
    return 0;
}

//
// Function: MulticastDriver
//
// Description:
//    Because the only difference between the sender and the
//    receiver is calling WSARecvFrom or WSASendTo, we implement
//    both sides in this one function.
//
void MulticastDriver(SOCKET s)
{
    WSANETWORKEVENTS ne;
    SOCKADDR_IN      mcast,
                     from,
                     local;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -