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

📄 qosudp.c

📁 《Windows网络编程技术》附书源码源码. 运行环境:9x/Me/NT/2000/XP/ 源码语言:简体中文 第十二章
💻 C
📖 第 1 页 / 共 2 页
字号:
// 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: Receiver
//
// Description:
//
void DoStuff(SOCKET s)
{
    WSANETWORKEVENTS  ne;
    WSAEVENT          hEvent;
    SOCKADDR_IN       from,
                      local;
    WSABUF            wbuf;
    DWORD             dwBytes,
                      dwFromLen,
                      dwFlags;
    QOS              *lpqos=NULL;
    char              rcvbuf[DATA_BUFFER_SZ],
                      sndbuf[DATA_BUFFER_SZ],
                      qosbuf[QOS_BUFFER_SZ];
    int               ret;

    // No matter when we decide to set QOS, the socket should be
    // bound locally (even if its to INADDR_ANY). This is required
    // if you're not using WSAConnect which does an implicit bind,
    // but we'll do it anyway for simplicity.
    //
    if (bSender)
    {
 	local.sin_family = AF_INET;
	local.sin_port = htons(5150); //0);
	local.sin_addr.s_addr = htonl(INADDR_ANY);
    }
    else
    {
        local.sin_family = AF_INET;
        local.sin_port = htons(5150);
        local.sin_addr.s_addr = htonl(INADDR_ANY);
    }
    if (bind(s, (SOCKADDR *)&local, sizeof(local)) == SOCKET_ERROR)
    {
        printf("bind() failed: %d\n", WSAGetLastError());
        return;
    }
    // For the receiver there's really only:
    //  1. Set QOS beforehand (SET_QOS_BEFORE)
    //  2. Set QOS upon an FD_QOS event (SET_QOS_EVENT);
    //
    if ((!bSender) && (iSetQos != SET_QOS_EVENT))
    {
        lpqos = &recvQos;
        if (SetQosReceivers(s, lpqos) == FALSE)
            return;
    }
    // For the sender you can:
    //  1. Set QOS before hand with SIO_SET_QOS (SET_QOS_BEFORE)
    //  2. Set QOS during WSAConnect (SET_QOS_DURING)
    //  3. Set QOS after WSAConnect (SET_QOSAFTER)
    //  4. Set QOS upon FD_QOS (SET_QOS_EVENT)
    //     (not really meaningful though - no RESV are generated
    //      by the receiver until it receives a PATH)
    //
    if ((bSender) && (iSetQos == SET_QOS_BEFORE))
    {
        // Set QOS before along with QOS_DESTADDR
        //
        lpqos = &sendQos;
        if (SetQosDestAddr(s, lpqos) == FALSE)
            return;
    }
    else if ((bSender) && (iSetQos == SET_QOS_DURING))
    {
        // Set QOS in WSAConnect call
        //
        SOCKADDR_IN   remote;

        lpqos = &sendQos;

        remote.sin_family = AF_INET;
        remote.sin_port = htons(5150);
        remote.sin_addr.s_addr = inet_addr(szReceiverAddr);
        printf("WSAConnect() to %s\n", inet_ntoa(remote.sin_addr));

        ret = WSAConnect(s, (SOCKADDR *)&remote, sizeof(remote), 
            NULL, NULL, lpqos, NULL);
        if (ret == SOCKET_ERROR)
        {
            printf("WSAConnect() failed: %d\n", WSAGetLastError());
            return;
        }
    }
    else if ((bSender) && (iSetQos == SET_QOS_AFTER))
    {
        // Call WSAConnect() without any QOS parametrs and then do
        // a SIO_SET_QOS. We don't use SetQosDestAddr() as it always
        // sets a QOS_DESTADDR object which isn't necessary since
        // we've already associated an endpoint address with the
        // WSAConnect() call.
        //
        SOCKADDR_IN   remote;

        remote.sin_family = AF_INET;
        remote.sin_port = htons(5150);
        remote.sin_addr.s_addr = inet_addr(szReceiverAddr);
        printf("WSAConnect() to %s (NO QOS)\n", inet_ntoa(remote.sin_addr));

        ret = WSAConnect(s, (SOCKADDR *)&remote, sizeof(remote), 
            NULL, NULL, NULL, NULL);
        if (ret == SOCKET_ERROR)
        {
            printf("WSAConnect() failed: %d\n", WSAGetLastError());
            return;
        }

        lpqos = &sendQos;
        ret = WSAIoctl(s, SIO_SET_QOS, lpqos, sizeof(QOS), NULL, 0,
            &dwBytes, NULL, NULL);
        if (ret == SOCKET_ERROR)
        {
            printf("WSAIoctl(SIO_SET_QOS) failed: %d\n",
                WSAGetLastError());
            return;
        }
    }
    if (iSetQos == SET_QOS_EVENT)
    {
        // Just register for FD_QOS events
        //
        if (bSender)
        {
            lpqos = &sendQos;
            lpqos->SendingFlowspec.ServiceType |= SERVICE_NO_QOS_SIGNALING;
        }
        else
        {
            lpqos = &recvQos;
            lpqos->ReceivingFlowspec.ServiceType |= SERVICE_NO_QOS_SIGNALING;
        }
        if (SetQosDestAddr(s, lpqos) == FALSE)
            return;
    }

    hEvent = WSACreateEvent();
    if (hEvent == WSA_INVALID_EVENT)
    {
        printf("WSACreateEvent() failed: %d\n", WSAGetLastError());
        return;
    }
 
    ret = WSAEventSelect(s, hEvent, FD_READ | FD_WRITE | FD_QOS);
    if (ret == SOCKET_ERROR)
    {
        printf("WSAEventSelect() failed: %d\n", WSAGetLastError());
        return;
    }

    while (1)
    {
        ret = WSAWaitForMultipleEvents(1, &hEvent, FALSE, 
            WSA_INFINITE, FALSE);
        if (ret == WSA_WAIT_FAILED)
        {
            printf("WSAWaitForMultipleEvents() failed: %d\n",
                WSAGetLastError());
            return;
        }

        ret = WSAEnumNetworkEvents(s, hEvent, &ne);
        if (ret == SOCKET_ERROR)
        {
            printf("WSAEnumNetworkEvents() failed: %d\n",
                WSAGetLastError());
            return;
        }
        if (ne.lNetworkEvents & FD_READ)
        {
            if (ne.iErrorCode[FD_READ_BIT])
            {
                printf("FD_READ error: %d\n", 
                    ne.iErrorCode[FD_READ_BIT]);
            }
            else
                printf("FD_READ\n");
            dwFromLen = sizeof(from);
            wbuf.buf = rcvbuf;
            wbuf.len = DATA_BUFFER_SZ;
            dwFlags = 0;

            ret = WSARecvFrom(s, &wbuf, 1, &dwBytes, &dwFlags,
                (SOCKADDR *)&from, &dwFromLen, NULL, NULL);
            if (ret == SOCKET_ERROR)
            {
                printf("WSARecvFrom() failed: %d\n", 
                    WSAGetLastError());
                return;
            }
        }
        if (ne.lNetworkEvents & FD_WRITE)
        {
            if (ne.iErrorCode[FD_WRITE_BIT])
            {
                printf("FD_WRITE error: %d\n",
                    ne.iErrorCode[FD_WRITE_BIT]);
            }
            else
                printf("FD_WRITE\n");
            if ((bSender) && (!bWaitToSend))
            {
                SOCKADDR_IN        receiver;

                memset(sndbuf, '$', DATA_BUFFER_SZ);
                wbuf.buf = sndbuf;
                wbuf.len = DATA_BUFFER_SZ - 1;

                receiver.sin_family = AF_INET;
                receiver.sin_port = htons(5150);
                receiver.sin_addr.s_addr = inet_addr(szReceiverAddr);

                ret = WSASendTo(s, &wbuf, 1, &dwBytes, 0, 
                    (SOCKADDR *)&receiver, sizeof(receiver), NULL, NULL);
                if (ret == SOCKET_ERROR)
                {
                    if (WSAGetLastError() == WSAEWOULDBLOCK)
                        continue;
                    printf("WSASendTo() failed: %d\n",
                        WSAGetLastError());
                    return;
                }
                printf("WSASendTo() wrote: %d bytes to %s\n",
                    dwBytes, inet_ntoa(receiver.sin_addr));
            }
        }
        if (ne.lNetworkEvents & FD_QOS)
        {
            if (ne.iErrorCode[FD_QOS_BIT])
            {
                if (ne.iErrorCode[FD_QOS_BIT] == WSA_QOS_RECEIVERS)
                {
                    printf("WSA_QOS_RECEIVERS\n");
                    bOkayToSend = TRUE;
                }
                else
                    printf("FD_QOS error: %d\n",
                        ne.iErrorCode[FD_QOS_BIT]);
            }
            printf("FD_QOS\n");

            lpqos = (QOS *)qosbuf;
            lpqos->ProviderSpecific.buf = &qosbuf[sizeof(QOS)];
            lpqos->ProviderSpecific.len = sizeof(qosbuf) - sizeof(QOS);

            ret = WSAIoctl(s, SIO_GET_QOS, NULL, 0, lpqos, 
                QOS_BUFFER_SZ, &dwBytes, NULL, NULL);
            if (ret == SOCKET_ERROR)
            {
                printf("WSAIoctl(SIO_GET_QOS) failed: %d\n",
                    WSAGetLastError());
                return;
            }
            PrintQos(lpqos);
            //
            // See if an RSVP_STATUS_INFO object has been returned
            //
            if (ChkForQosStatus(lpqos, WSA_QOS_RECEIVERS))
                bOkayToSend = TRUE;

            if ((bWaitToSend) && (bOkayToSend))
            {
                SOCKADDR_IN        receiver;

                memset(sndbuf, '$', DATA_BUFFER_SZ);
                wbuf.buf = sndbuf;
                wbuf.len = DATA_BUFFER_SZ - 1;

                receiver.sin_family = AF_INET;
                receiver.sin_port = htons(5150);
                receiver.sin_addr.s_addr = inet_addr(szReceiverAddr);
        
                ret = WSASendTo(s, &wbuf, 1, &dwBytes, 0, 
                    (SOCKADDR *)&receiver, sizeof(receiver), NULL, NULL);
                if (ret == SOCKET_ERROR)
                {
                    if (WSAGetLastError() == WSAEWOULDBLOCK)
                        continue;
                    printf("WSASendTo() failed: %d\n",
                        WSAGetLastError());
                    return;
                }
                printf("WSASendTo() wrote: %d bytes to %s\n",
                    dwBytes, inet_ntoa(receiver.sin_addr));
            }
            if (iSetQos == SET_QOS_EVENT)
            {
                if (bSender)
                    lpqos->SendingFlowspec.ServiceType = 
                        sendQos.SendingFlowspec.ServiceType;
                else
                    lpqos->ReceivingFlowspec.ServiceType = 
                        recvQos.ReceivingFlowspec.ServiceType;
                ret = WSAIoctl(s, SIO_SET_QOS, lpqos, sizeof(QOS), 
                    NULL, 0, &dwBytes, NULL, NULL);
                if (ret == SOCKET_ERROR)
                {
                    printf("WSAIoctl(SIO_SET_QOS) failed: %d\n",
                        WSAGetLastError());
                    return;
                }
                iSetQos = SET_QOS_BEFORE;
            }
        }
    }
}

//
// Function: main
//
// Description:
//
int main(int argc, char **argv)
{
    WSADATA           wsd;
    WSAPROTOCOL_INFO *pinfo=NULL;
    SOCKET            s;

    ValidateArgs(argc, argv);

    if (WSAStartup(MAKEWORD(2,2), &wsd) != 0)
    {
        printf("Unable to load Winsock: %d\n", GetLastError());
        return -1;
    }
    pinfo = FindProtocolInfo(AF_INET, SOCK_DGRAM, IPPROTO_UDP,
                XP1_QOS_SUPPORTED);
    if (!pinfo)
    {
        printf("unable to find suitable provider!\n");
        return -1;
    }
    printf("Provider returned: %s\n", pinfo->szProtocol); 
   
    s = WSASocket(FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO, 
                FROM_PROTOCOL_INFO, pinfo, 0, WSA_FLAG_OVERLAPPED);
    if (s == INVALID_SOCKET)
    {
        printf("WSASocket() failed: %d\n", WSAGetLastError());
        return -1;
    }

    InitQos();

    DoStuff(s);

    closesocket(s);
    WSACleanup();
    return 0;
}

⌨️ 快捷键说明

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