title: Receiving Multicast Messages on a Multihomed Windows PC
body: <p>I'm developing a diagnostic tool on a PC with several Network Interfaces based on multicast/udp. The user can select a NIC, the application creates sockets, binds them to this NIC and adds them to the specific multicast group.</p>
  
  <p>The sending of multicast messages works fine. However receiving of messages only succeeds if I bind the sockets to a specific NIC of my PC. It almost looks like as there is a 'default' NIC for receiving multicast messages in Windows which is always the first NIC returned by the <strong>GetAdapterInfo</strong> function.</p>
  
  <p>I monitored the network with Wireshark and discovered that the "IGMP Join Group" message isn't sent from the NIC I bound the socket at, but by this 'default' NIC.</p>
  
  <p>If I disable this NIC (or remove the network cable), the next NIC of the list returned by GetAdapterInfo is used for receiving multicast messages.</p>
  
  <p>I was successful to change this 'default' NIC by adding an additional entry to the routing table of my PC, but I don't think this is a good solution of the problem.</p>
  
  <p>The problem also occurs with the code appended below. The join group messages isn't sent via 192.168.52 but via a different NIC.</p>
  
  <pre><code>// socket_tst.cpp : Defines the entry point for the console application.
  //
  
  \#include tchar.h
  \#include winsock2.h
  \#include ws2ipdef.h
  \#include IpHlpApi.h
  \#include IpTypes.h
  
  \#include stdio.h
  
  int _tmain(int argc, _TCHAR* argv[])
  {
    WSADATA       m_wsaData;
    SOCKET        m_socket;
    sockaddr_in   m_sockAdr;
    UINT16        m_port = 319;
    u_long        m_interfaceAdr = inet_addr("192.168.1.52");
    u_long        m_multicastAdr = inet_addr("224.0.0.107");
  
    int returnValue = WSAStartup(MAKEWORD(2,2), &amp;m_wsaData);
    if (returnValue != S_OK)
    {
      return returnValue;
    }
  
    // Create sockets
    if (INVALID_SOCKET == (m_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) )
    {
      return WSAGetLastError();
    }
  
    int doreuseaddress = TRUE;
    if (setsockopt(m_socket,SOL_SOCKET,SO_REUSEADDR,(char*) &amp;doreuseaddress,sizeof(doreuseaddress)) == SOCKET_ERROR)
    {
      return  WSAGetLastError(); 
    }
  
    // Configure socket addresses
    memset(&amp;m_sockAdr,0,sizeof(m_sockAdr));
    m_sockAdr.sin_family =        AF_INET;
    m_sockAdr.sin_port =          htons(m_port);   
    m_sockAdr.sin_addr.s_addr =   m_interfaceAdr;
  
    //bind sockets
    if ( bind( m_socket, (SOCKADDR*) &amp;m_sockAdr, sizeof(m_sockAdr) )  == SOCKET_ERROR )
    {
      return  WSAGetLastError();
    }
  
    // join multicast
    struct ip_mreq_source imr; 
  
    memset(&amp;imr,0,sizeof(imr));
    imr.imr_multiaddr.s_addr  = m_multicastAdr; // address of multicastgroup
    imr.imr_sourceaddr.s_addr = 0;              // sourceaddress (not used)
    imr.imr_interface.s_addr  = m_interfaceAdr; // interface address
    /* first join multicast group, then registerer selected interface as 
    * multicast sending interface */
    if( setsockopt( m_socket 
                    ,IPPROTO_IP
                    ,IP_ADD_MEMBERSHIP
                    ,(char*) &amp;imr
                    , sizeof(imr)) 
                    == SOCKET_ERROR)
    {
      return SOCKET_ERROR;
    }
    else
    {
      if( setsockopt(m_socket 
                    ,IPPROTO_IP
                    ,IP_MULTICAST_IF
                    ,(CHAR*)&amp;imr.imr_interface.s_addr
                    ,sizeof(&amp;imr.imr_interface.s_addr)) 
                    == SOCKET_ERROR )
      {
        return SOCKET_ERROR;
      }
    }
  
    printf("receiving msgs...\n");
    while(1)
    {
      // get inputbuffer from socket
      int sock_return = SOCKET_ERROR;
      sockaddr_in socketAddress;
      char buffer[1500];
  
      int addressLength = sizeof(socketAddress);
      sock_return = recvfrom(m_socket, (char*) &amp;buffer, 1500, 0, (SOCKADDR*)&amp;socketAddress, &amp;addressLength );
      if( sock_return == SOCKET_ERROR)
      {
        int wsa_error = WSAGetLastError();
        return wsa_error;
      } 
      else
      {
        printf("got message!\n");
      }
    }
  
    return 0;
  }
  </code></pre>
  
  <p>Thanks four your help!</p>