UDP multicast problem with winsock

Discussion in 'C++' started by Gary C, May 18, 2010.

  1. Gary C

    Gary C Guest

    Apologies in advance if this newsgroup is considered not relevent, if
    so please suggest one that is.

    I have a situation where i need to receive UDP multicasts on a
    computer that has multiple network cards. The problem i am
    experiencing is that the udp packets are arriving on the network card
    of interest (i have run a network analysis application to verify this)
    but something is blocking the data from arriving on the open socket.
    Following the advice from an older post i have run TDIMon.exe also and
    can confirm that the 'TDI_EVENT_RECEIVE_DATAGRAM' message is not
    reported when the messages are not received which as i understand it
    implies that the received data is being blocked somewhere in the
    protocol stack.

    If i disable the other network cards the messages get through.

    I have tried the same broadcast code against a program that uses a
    third party UDP comms component under the same network conditions and
    the multicast is received successfully so i strongly suspect i am
    doing something wrong in my winsock udp code.

    I have stripped the code out of a much larger application that is
    experiencing this problem into a console application and can confirm
    the same behaviour (code listing to follow). Any help would be greatly
    appreciated, the environment is Windows XP SP2, the code is compiled
    under BCB2007 but #pragmas aside it should compile under most windows c
    ++ compilers.

    In the version given below i am using 'INADDR_ANY' as the transmission
    host address, this is from a machine with a single network card, the
    same behaviour was achieved when using 'szHostAddress'.

    If i run the application with option 1 on the system with multiple
    active cards it will listen for multicast data on '234.5.6.7', if i
    then run the application on a networked system with option 2 the
    application sends the sample message 10 times before returning, the
    listener does not pick up the transmissions. If i disable the
    additional cards on the listener and re-run the listener application
    it receives the messages.

    I did also notice (although the test app below will not reproduce the
    scenario) that one the receive socket is open on the system with the
    network cards disabled, if i then re-enable them transmissions are
    received, if the socket is closed and a new one opened however the
    transmissions are no longer received. In all scenarios i have
    confirmed that the UDP packets are arriving on the listeners network.

    Once again all suggestions would be greatly appreciated.
    Many thanks
    Gary

    //---------------------------------------------------------------------------
    //-UDP_TESTAPP
    //---------------------------------------------------------------------------
    #include <iostream.h>
    #include <winsock2.h>
    #include <ws2tcpip.h>

    //---------------------------------------------------------------------------
    bool InitialiseWinsock();
    void CleanupWinsock();
    int main_client();
    int main_server();
    //---------------------------------------------------------------------------
    // definitions
    const char* szHostAddress = "10.10.10.7";
    const char* szMultiAddress = "234.5.6.7";
    const char* szMessage = "Sample multicast message!";
    const int iMaxBuffer= 500;
    const int iPortNumber = 50326;
    //---------------------------------------------------------------------------
    // globals
    SOCKET g_Socket = INVALID_SOCKET;

    #pragma hdrstop

    //---------------------------------------------------------------------------

    #pragma argsused
    //---------------------------------------------------------------------------
    int main(int argc, char* argv[])
    {
    int choice = 0;

    while (choice != 3)
    {
    cout <<"Enter choice:"<< endl <<
    "1)Run UDP multicast listener." << endl <<
    "2)Run UDP multicast transmitter." << endl<<
    "3)quit" << endl;

    cin >> choice;

    switch(choice) {
    case 1:
    main_server();
    break;
    case 2:
    main_client();
    break;

    default:
    choice = 3;
    break;
    }
    };

    return 0;
    }
    //---------------------------------------------------------------------------
    int main_client()
    {
    if (!InitialiseWinsock()) {
    return -1;
    }

    // create our socket
    g_Socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    if (INVALID_SOCKET == g_Socket) {
    cerr << "Failed to create socket, WSAGetLastError returned " <<
    WSAGetLastError() << endl;
    CleanupWinsock();
    return -1;
    }

    // allow use of address already in use
    int iReuse = 1;
    if (0 != setsockopt(g_Socket, SOL_SOCKET, SO_REUSEADDR,
    (char*)&iReuse,
    sizeof(int))) {
    cerr << "Failed to set option 'SO_RESUEADDR' on socket,
    WSAGetLastError "
    "returned " << WSAGetLastError() << endl;
    CleanupWinsock();
    return -1;
    }

    SOCKADDR_IN SockAddr;
    // initialise
    memset(&SockAddr, 0, sizeof(SOCKADDR_IN));
    // populate
    SockAddr.sin_family = AF_INET;
    // SockAddr.sin_addr.s_addr = inet_addr(szHostAddress);
    SockAddr.sin_addr.s_addr = htonl(INADDR_ANY);
    SockAddr.sin_port = htons(iPortNumber);

    // bind to the socket
    if (0 != bind(g_Socket, (const sockaddr*)&SockAddr,
    sizeof(SOCKADDR_IN))) {
    cerr << "Failed to bind socket for transmission. WSAGetLastError "
    "returned " << WSAGetLastError() << endl;
    CleanupWinsock();
    return -1;
    }

    IN_ADDR iAddr;
    iAddr.s_addr = inet_addr(szHostAddress);
    if (0 != setsockopt(g_Socket, IPPROTO_IP, IP_MULTICAST_IF,
    (char*)&iAddr,
    sizeof(IN_ADDR))) {
    cerr << "Failed to set option 'IP_MULTICAST_IF' on socket,
    WSAGetLastError "
    "returned " << WSAGetLastError() << endl;
    CleanupWinsock();
    return -1;
    }

    // N.B. this sets a limit on router hops for the multicast after
    which the
    // message is discarded. On a direct connection to a DIU there are no
    routers
    // so this does not have to be set (its default value of 1 is
    sufficient)
    // int iTTL = 3; // set to whatever is required for network
    // if (0 != setsockopt(g_Socket, IPPROTO_IP, IP_MULTICAST_TTL,
    (char*)&iTTL,
    // sizeof(int))) {
    // cerr << "Failed to set option 'IP_MULTICAST_TTL' on socket,
    WSAGetLastError "
    // "returned " << WSAGetLastError() << endl;
    // CleanupWinsock();
    // return -1;
    // }

    // prepare the destination address
    SOCKADDR_IN DestAddr;
    // initialise
    memset(&DestAddr, 0, sizeof(SOCKADDR_IN));
    // populate
    DestAddr.sin_family = AF_INET;
    DestAddr.sin_addr.s_addr = inet_addr(szMultiAddress);
    DestAddr.sin_port = htons(iPortNumber);

    int iLen = strlen(szMessage);
    int iCount = 0;
    int iMax = 10;
    const char* pDataBuf = szMessage;

    cout << "Sending '" << szMessage << "' " << iMax << " times." <<
    endl;

    while (1) {
    if (iLen != sendto(g_Socket, pDataBuf, iLen, 0, (const
    sockaddr*)&DestAddr,
    sizeof(SOCKADDR_IN))) {
    cerr << "Failed to send expected " << iLen << " bytes. "
    "WSAGetLastError returned " << WSAGetLastError() << endl;
    break;
    }

    iCount += 1;

    if (iCount > 10) {
    break;
    }

    if (iCount > 1) {
    cout << ", " << iCount;
    }
    else {
    cout << iCount;
    }

    Sleep(100);
    };

    // final cleanup
    CleanupWinsock();

    return 0;
    }
    //---------------------------------------------------------------------------
    int main_server()
    {
    if (!InitialiseWinsock()) {
    return -1;
    }

    // create our socket
    g_Socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    if (INVALID_SOCKET == g_Socket) {
    cerr << "Failed to create socket, WSAGetLastError returned " <<
    WSAGetLastError() << endl;
    CleanupWinsock();
    return -1;
    }

    SOCKADDR_IN SockAddr;
    // initialise
    memset(&SockAddr, 0, sizeof(SOCKADDR_IN));
    // populate
    SockAddr.sin_family = AF_INET;
    SockAddr.sin_addr.s_addr = htonl(INADDR_ANY);
    SockAddr.sin_port = htons(iPortNumber);

    // bind to the socket
    if (0 != bind(g_Socket, (const sockaddr*)&SockAddr,
    sizeof(SOCKADDR_IN))) {
    cerr << "Failed to bind socket for reception. WSAGetLastError "
    "returned " << WSAGetLastError() << endl;
    CleanupWinsock();
    return -1;
    }

    ip_mreq mreq;
    mreq.imr_multiaddr.s_addr = inet_addr(szMultiAddress);
    mreq.imr_interface.s_addr = htonl(INADDR_ANY);

    if (0 != setsockopt(g_Socket, IPPROTO_IP, IP_ADD_MEMBERSHIP,
    (char*)&mreq,
    sizeof(ip_mreq))) {
    cerr << "Failed to set option 'IP_ADD_MEMBERSHIP' on socket,
    WSAGetLastError "
    "returned " << WSAGetLastError() << endl;
    CleanupWinsock();
    return -1;
    }

    int iLen = strlen(szMessage);
    int iCount = 0;
    int iMax = 10;
    char buffer[iMaxBuffer];
    int iSockAddrLen = sizeof(SOCKADDR_IN);

    cout << "Listening for '" << iMax << "' multicast messages on '" <<
    szMultiAddress << "'..."<< endl;

    while (1) {
    iLen = recvfrom(g_Socket, buffer, iMaxBuffer, 0,
    (sockaddr*)&SockAddr, &iSockAddrLen);
    if (iLen > 0) {
    iCount += 1;
    cout << "Received message #" << iCount << " : " << (const
    char*)buffer
    << endl;
    }

    if (iCount > iMax) {
    break;
    }

    Sleep(100);
    };

    // final cleanup
    CleanupWinsock();
    return 0;
    }
    //---------------------------------------------------------------------------
    bool InitialiseWinsock()
    {
    WORD wVersionRqd;
    WSADATA wsaData;

    // set the version
    wVersionRqd = MAKEWORD(2,2);

    if (0 != WSAStartup(wVersionRqd, &wsaData)) {
    cerr << "Call to WSAStartup failed, WSAGetLastError returned " <<
    WSAGetLastError() << endl;
    return false;
    }

    return true;
    }
    //---------------------------------------------------------------------------
    void CleanupWinsock()
    {
    if (INVALID_SOCKET != g_Socket) {
    if (0 != shutdown(g_Socket, SD_BOTH)) {
    cerr << "shutdown call failed for socket, WASGetLastError returned
    " <<
    WSAGetLastError() << endl;
    }
    if (0 != closesocket(g_Socket)) {
    cerr << "closesocket call failed for socket, WASGetLastError "
    "returned " << WSAGetLastError() << endl;
    }

    g_Socket = INVALID_SOCKET;
    }

    if (0 != WSACleanup()) {
    cerr << "WSACleanup call failed, WSAGetLastError returned " <<
    WSAGetLastError() << endl;
    }
    }
    Gary C, May 18, 2010
    #1
    1. Advertising

  2. On 5/18/2010 12:16 PM, Gary C wrote:
    > Apologies in advance if this newsgroup is considered not relevent, if
    > so please suggest one that is.


    C++ language has no support for UDP/multicast/sockets. That all is
    provided by your platform through platform-specific libraries.

    You need the newsgroup that discusses your OS. For Windows, it's
    usually in the 'comp.os.ms-windows.*' hierarchy, or you could find
    another one in 'microsoft.public.*' family of newsgroups.

    Good luck!

    >[...]


    V
    --
    I do not respond to top-posted replies, please don't ask
    Victor Bazarov, May 18, 2010
    #2
    1. Advertising

  3. Gary C

    Jorgen Grahn Guest

    On Tue, 2010-05-18, Victor Bazarov wrote:
    > On 5/18/2010 12:16 PM, Gary C wrote:
    >> Apologies in advance if this newsgroup is considered not relevent, if
    >> so please suggest one that is.

    >
    > C++ language has no support for UDP/multicast/sockets. That all is
    > provided by your platform through platform-specific libraries.
    >
    > You need the newsgroup that discusses your OS. For Windows, it's
    > usually in the 'comp.os.ms-windows.*' hierarchy, or you could find
    > another one in 'microsoft.public.*' family of newsgroups.


    comp.protocols.tcp-ip is also a good group for this kind of thing.
    They have a few Windows socket programmers, and lots of people who
    do exotic things like multicast.

    But please dump the code in a pastebin -- it was a bit longer than
    examples usually are on that group.

    /Jorgen

    --
    // Jorgen Grahn <grahn@ Oo o. . .
    \X/ snipabacken.se> O o .
    Jorgen Grahn, May 19, 2010
    #3
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Replies:
    7
    Views:
    648
    CBFalconer
    Dec 1, 2006
  2. Replies:
    0
    Views:
    417
  3. udp multicast server and client

    , Apr 25, 2008, in forum: C Programming
    Replies:
    3
    Views:
    813
    Sri Harsha Dandibhotla
    Apr 25, 2008
  4. inorlando
    Replies:
    3
    Views:
    1,269
    castironpi
    Aug 29, 2008
  5. neilsolent

    UDP Multicast Question

    neilsolent, Jan 21, 2009, in forum: Java
    Replies:
    2
    Views:
    716
    neilsolent
    Jan 22, 2009
Loading...

Share This Page