Solved

Why can't I join a multicast group

Posted on 2004-10-05
15
935 Views
Last Modified: 2012-08-14
I am trying to join a multi cast group but I am getting WSAENOPROTOOPT, 10042  returned by WSAGetLastError.  When I look at the fields populated in the ip_mreq struct the curret ip values are there 10.10.10.1 for interface and 227.10.10.10 for multicast group.  Following is a snippet of code which I am trying to get to work, along with debugging stuff to check values in the debugger.  Any suggestions on where to start looking for the fix for this?


// request to join group    
    ip_mreq req;

    // get the currently selected local interface.
    req.imr_interface = m_hostIPs[m_IPIndex];

    MulticastGroups::const_iterator it = m_joinedGroups.begin();
    MulticastGroups::const_iterator ite = m_joinedGroups.end();
   
    while (it != ite) {
        long group = inet_addr(it->c_str());

        memcpy(&req.imr_multiaddr, &group, sizeof(group));
        char* str = inet_ntoa(req.imr_interface);
        str = inet_ntoa(req.imr_multiaddr);
        int x = setsockopt(m_recvSocket, IPPROTO_IP, IP_ADD_SOURCE_MEMBERSHIP,
                   (char*)&req, sizeof(req));
        x= WSAGetLastError();
        it++;
    }
0
Comment
Question by:mvoiers
  • 6
  • 6
15 Comments
 

Author Comment

by:mvoiers
ID: 12230849
In case it matters I am running Windows 2k and visual studio 2003.  Also another way to look at this, I want to call setsockopt with an ip_mreq populated with two ip address, (local interface and group),  and the option IP_ADD_SOURCE_MEMBERSHIP.  I have already created a socket with the following socket(AF_INET, SOCK_DGRAM, 0).
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 12248440
MSDN says that IPPROTO_IP and IP_ADD_SOURCE_MEMBERSHIP is only valid for WinXP and Server 2003.

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winsock/winsock/ipproto_ip_socket_options.asp

Regards, Alex
0
 

Author Comment

by:mvoiers
ID: 12249173
Yes, I caught the IP_ADD_SOURCE_MEMBERSHIP and replaced it with IP_ADD_MEMBERSHIP...still no luck.  Another question I have run into which I think I know the answer is that I just need one socket which I can join numerous groups on, I don't need to create a socket for each group?  

Here is how I am trying to read from the sockets, I think it is safe to say I can ditch this iteration over multiple sockets and just use one socket, but either way I don't seem to be having any luck....

    SocketsList::const_iterator it = m_recvSocket.begin();
    SocketsList::const_iterator ite = m_recvSocket.end();
    int byteCount = 0;
    for (; it != ite; it++)
    {
        for (int i = 0; i < m_maxReads; i++, byteCount++)
        {
            // read from the socket
            numBytes = recvfrom(*it, buffer, s_defaultMaxBuffer, 0,
                reinterpret_cast<sockaddr *>(&fromAddress), &fromLength);

            // check to make sure there wasn't an error
            if (numBytes < 0)
            {
//                return byteCount;
                break;
            }

            // pass buffer to handler code
     
        }
    }

0
Back Up Your Microsoft Windows Server®

Back up all your Microsoft Windows Server – on-premises, in remote locations, in private and hybrid clouds. Your entire Windows Server will be backed up in one easy step with patented, block-level disk imaging. We achieve RTOs (recovery time objectives) as low as 15 seconds.

 

Author Comment

by:mvoiers
ID: 12249814
after joining numerous groups I perform a bind, passing in the ip address of my desired local interface.    All the winsock calls return without error.  The one thing that is concerning me is that I only receive packets on my unicast address, which is the address I don't want to receive anything on if I am in multicast.  Anything sent to the multicast address is never received....no matter what I try.  I am now back to creating just one socket and doing joins on that socket instead of creating a socket for each join.  I believe this is the correct approach instead of creating a socket for each join.

Here is basically what I am doing now

// create a socket, there doesn't seem to be any other options here
m_recvSocket = socket(AF_INET, SOCK_DGRAM, 0);

    // go through all the groups we want to join and join then using setsockopt
    MulticastGroups::const_iterator it = m_joinedGroups.begin();
    MulticastGroups::const_iterator ite = m_joinedGroups.end();
   
    while (it != ite) {
        long group = inet_addr(it->c_str());

        memcpy(&mreq.imr_multiaddr, &group, sizeof(group));
        char* str = inet_ntoa(mreq.imr_interface);
        str = inet_ntoa(mreq.imr_multiaddr);
        int x = setsockopt(m_recvSocket, IPPROTO_IP, IP_ADD_MEMBERSHIP,
                           (char*)&mreq, sizeof(mreq));
        x = WSAGetLastError();
        it++;
    }


    char reuseaddr = 1;
    int r = setsockopt(m_recvSocket, SOL_SOCKET, SO_REUSEADDR, &reuseaddr,
        sizeof(reuseaddr));

    // bind the input socket to the DIS port
    struct sockaddr_in address;

    memset(&address, 0, sizeof(address)) ;
    address.sin_family      = AF_INET;
    address.sin_port        = htons(m_port);
    address.sin_addr        = hostAddr;

   

    int x = bind(m_recvSocket, reinterpret_cast<const sockaddr *>(&address),
        sizeof(address));
    x = WSAGetLastError();

    // setup the input socket for nonblocking I/O
    unsigned long flags = 1;
    if (ioctlsocket(m_recvSocket, FIONBIO, &flags) != 0)



// now to read something

numBytes = recvfrom(m_recvSocket, buffer, s_defaultMaxBuffer, 0,
            reinterpret_cast<sockaddr *>(&fromAddress), &fromLength);


this is the jist of all the code....can anyone see any glaring errors?  

0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 12249985
Did you convert hostAddr by using htonl ?
Did you get any errors or simply nothing to receive?
Did you try a TCP/IP connection before?
Is there any firewall that could prevent you from receiving messages?

Regards, Alex


0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 12250033
If you set the socket to non-blocking recvfrom most likely returns not reading anything. You have to check  WSAGetLastError() if it equals WAE_WOULDBLOCK. That is ok, and you have to poll after sleeping some milliseconds til you'll get anything.

Regards, Alex


   
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 12250054
Correction: it's WSAEWOULDBLOCK.
0
 

Author Comment

by:mvoiers
ID: 12250387
memcpy(&hostAddr, &ladr, sizeof(unsigned long));

I look at the hostAddr struct in the debugger and it contains the correst IP.


I do get the WSAEWOULDBLOCK when I try to receive.

As for TCP/IP if I do a unicast transmission, I get everything fine.  Its just when I tell my packet generation program to go multicast I never see anything.  I can see the packets being generated using the Ethereal packet sniffer and the source and destination ip address looks good.





0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 12250637
>>>> I look at the hostAddr struct in the debugger and it contains the correst IP

but hostAddr should be in net order that is big endian (means byte order is 3 2 1 0). You should try

    address.sin_addr = htonl(hostAddr);

However, if it worked with TCP/IP the address is ok.

>>>> I do get the WSAEWOULDBLOCK when I try to receive.

As i told you: WSAEWOULDBLOCK is the "normal" error return after setting a socket to non-blocking. You need an endless loop like that to receive data:

    while (true)
    {
          numBytes = recvfrom(m_recvSocket, buffer, s_defaultMaxBuffer, 0,
            reinterpret_cast<sockaddr *>(&fromAddress), &fromLength);
          if (numBytes == SOCKET_ERROR)
          {
               unsigned int err = WSAGetLastError());
               if (err == WSAEWOULDBLOCK)
               {
                       Sleep(10);   // give other threads some process time
                       continue;     // try again
               }
               // error
               return 1;
          }
          // received data      

    }

Regards, Alex
   

   
0
 

Author Comment

by:mvoiers
ID: 12250864
Yes, the function the recvfrom call is in is called endlessly....otherwise the unicast wouldn't work either.  Since when I broadcast in unicast everything works fine, that would seem to suggest the framework is ok, just missing some sort of winsock config or other issue?



0
 

Author Comment

by:mvoiers
ID: 12251577
Well...looks like I get the points myself....the "join group had to take place after the bind".....jeeesh....join group should return an error if socket already bound.


0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 12256955
Gratulations. Try to accept your own comment ;-)  or go CS

Regards, Alex
0
 

Accepted Solution

by:
modulo earned 0 total points
ID: 12723901
PAQed with points refunded (500)

modulo
Community Support Moderator
0

Featured Post

PRTG Network Monitor: Intuitive Network Monitoring

Network Monitoring is essential to ensure that computer systems and network devices are running. Use PRTG to monitor LANs, servers, websites, applications and devices, bandwidth, virtual environments, remote systems, IoT, and many more. PRTG is easy to set up & use.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
Building cUrl in Windows v7.43.0 4 32
Arduino EDI - Programming language 3 95
Create a path if not exists 7 77
passing data from one form to another form in c++ 27 80
Errors will happen. It is a fact of life for the programmer. How and when errors are detected have a great impact on quality and cost of a product. It is better to detect errors at compile time, when possible and practical. Errors that make their wa…
Templates For Beginners Or How To Encourage The Compiler To Work For You Introduction This tutorial is targeted at the reader who is, perhaps, familiar with the basics of C++ but would prefer a little slower introduction to the more ad…
The viewer will learn how to use the return statement in functions in C++. The video will also teach the user how to pass data to a function and have the function return data back for further processing.
The viewer will be introduced to the technique of using vectors in C++. The video will cover how to define a vector, store values in the vector and retrieve data from the values stored in the vector.

809 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question