Проблемы с UDP-multicast
От: yourSensey  
Дата: 22.07.11 13:26
Оценка:
Только начал разбираться с работой udp-multicast. Под это есть задача написать небольшое приложение, подключающееся к multicast-группе и получающее с сервера данные.
Программа в целом написана. Она без проблем присоединяется к мулькаст-группе и сервер даже начинает слать данные(это видно в снифере Wireshark, мониторящем трафик на данной машине).

Проблема в том, что программа данных с боевого сервера не видит. Т.е. recvfrom() не отрабатывает. Однако, клиент исправно получает все пакеты от простейшего multicast-сервера, написанного мной и запущенного на той же машине, что и клиент. В Wireshark разницу в пакетах с локального тестового сервера и с удалённого боевого не заметил.

В чём может быть проблема? Может быть, требуется дополнительная настройка OC?

Код написан в MS VC2010 с Winsock2. ОС на тестируемой машине — Windows Server 2008 SP2.

Собственно код клиента:

    #ifndef UNICODE
    #define UNICODE
    #endif
    #define WIN32_LEAN_AND_MEAN
    #include <winsock2.h>
    #include <Ws2tcpip.h>
    #include <stdio.h>
    #include <mswsock.h>
     
    // Link with ws2_32.lib
    #pragma comment(lib, "Ws2_32.lib")
    #define u_int32 UINT32  // Unix uses u_int32
     
    #define RECV_IP_ADDR    "224.5.5.13"    // arbitrary multicast address
    #define MY_IP_ADDR      "192.168.1.2"   //
     
    int                  /* OUT: whatever setsockopt() returns */
    join_source_group(int sd, u_int32 grpaddr,
       u_int32 srcaddr, u_int32 iaddr)
    {
       struct ip_mreq_source imr;
       memset(&imr, 0, sizeof(imr));
     
       imr.imr_multiaddr.s_addr  = grpaddr;
       imr.imr_sourceaddr.s_addr = srcaddr;
       imr.imr_interface.s_addr  = iaddr;
       return setsockopt(sd, IPPROTO_IP, IP_ADD_SOURCE_MEMBERSHIP, (char *) &imr, sizeof(imr));
    }
     
    int
    leave_source_group(int sd, u_int32 grpaddr,
       u_int32 srcaddr, u_int32 iaddr)
    {
       struct ip_mreq_source imr;
     
       imr.imr_multiaddr.s_addr  = grpaddr;
       imr.imr_sourceaddr.s_addr = srcaddr;
       imr.imr_interface.s_addr  = iaddr;
       return setsockopt(sd, IPPROTO_IP, IP_DROP_SOURCE_MEMBERSHIP, (char *) &imr, sizeof(imr));
    }
     
    int main(int argc, char * argv[])
    {
        if (argc < 3)
        {
            wprintf(L"Need a server IP and your local IP\n");
            return 1;
        }
        char recvIpAddr[16] = RECV_IP_ADDR;
        char myIpAddr[16] = MY_IP_ADDR;
        strncpy(recvIpAddr, argv[1], 15);
        strncpy(myIpAddr, argv[2], 15);
     
        int iResult = 0;
     
        WSADATA wsaData;
     
        SOCKET RecvSocket;
        sockaddr_in RecvAddr;
     
        char RecvBuf[1024];
        int BufLen = 1024;
     
        sockaddr_in SenderAddr;
        int SenderAddrSize = sizeof(SenderAddr);
        memset(&SenderAddr, 0, SenderAddrSize);
     
        //-----------------------------------------------
        // Initialize Winsock
        iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
        if (iResult != NO_ERROR) {
            wprintf(L"WSAStartup failed with error %d\n", iResult);
            return 1;
        }
        //-----------------------------------------------
        // Create a receiver socket to receive datagrams
        RecvSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
        if (RecvSocket == INVALID_SOCKET) {
            wprintf(L"socket failed with error %d\n", WSAGetLastError());
            return 1;
        }
     
        int one = 1;
        if ( setsockopt(RecvSocket, IPPROTO_IP, SO_REUSEADDR, (char *)&one, sizeof(one)) == SOCKET_ERROR)
        {
        wprintf(L"Error setting SO_REUSEADDR!");
        return 1;
        }
     
        //-----------------------------------------------
        // Bind the socket to any address and the specified port.
        volatile unsigned short Port = 61000;
     
        memset(&RecvAddr, 0, sizeof(RecvAddr));
        RecvAddr.sin_family = AF_INET;
        RecvAddr.sin_port = htons(61000);
        RecvAddr.sin_addr.s_addr = htonl(INADDR_ANY);
     
        iResult = bind(RecvSocket, (SOCKADDR *) & RecvAddr, sizeof (RecvAddr));
        if (iResult != 0) {
            wprintf(L"bind failed with error %d\n", WSAGetLastError());
            return 1;
        }
     
        join_source_group(RecvSocket, inet_addr(recvIpAddr), inet_addr(myIpAddr), INADDR_ANY);
     
        //-----------------------------------------------
        // Call the recvfrom function to receive datagrams
        // on the bound socket.
        wprintf(L"Receiving datagrams...\n");
        while (1)
        {
        iResult = recvfrom(RecvSocket, RecvBuf, BufLen, 0, (SOCKADDR *) & SenderAddr, &SenderAddrSize);
     
        if (iResult == SOCKET_ERROR) {
            wprintf(L"recvfrom failed with error %d\n", WSAGetLastError());
        }
        RecvBuf[iResult] = 0;
        printf("recvfrom %s\n", RecvBuf);
        }
     
        //-----------------------------------------------
        // Close the socket when finished receiving datagrams
        wprintf(L"Finished receiving. Closing socket.\n");
        iResult = closesocket(RecvSocket);
        if (iResult == SOCKET_ERROR) {
            wprintf(L"closesocket failed with error %d\n", WSAGetLastError());
            return 1;
        }
     
        //-----------------------------------------------
        // Clean up and exit.
        wprintf(L"Exiting.\n");
        WSACleanup();
        return 0;
    }
multicast winsock2
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.