Solved

Why can't I join a multicast group

Posted on 2004-10-05
15
933 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
 

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
Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

 
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

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

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

Suggested Solutions

Title # Comments Views Activity
Visual c++ and text files 7 60
C++ Language error 28 197
operator overload: incompatible type and too many params 5 65
c++, dynamic object by json 1 25
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…
Written by John Humphreys C++ Threading and the POSIX Library This article will cover the basic information that you need to know in order to make use of the POSIX threading library available for C and C++ on UNIX and most Linux systems.   [s…
The viewer will learn additional member functions of the vector class. Specifically, the capacity and swap member functions will be introduced.
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.

863 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

Need Help in Real-Time?

Connect with top rated Experts

22 Experts available now in Live!

Get 1:1 Help Now