Search code examples
c++iosmacossocketsudp

Mac/iOS cannot receive UDP broadcast packet, but can send UDP broadcast packet


I am working on a cross-platform game using C/C++ and socket. I am using UDP broadcast (e.g. send to xx.xx.xx.255 if on a C-type LAN address) for discovering of nearby players in LAN game playing.

The issue is the Mac/iOS version can not receive broadcast UDP packet that sent by others (neither from Mac/iOS , nor from windows), while windows version is able the receive broadcast packet from Mac/iOS. Thus Mac/iOS can not discover any nearby players while windows can discover all nearby players. On the same socket handle, sending/receiving normal UDP packet works on all platforms (sent to a specific address instead of the broadcast address).

Every testing device has only one NIC, which is connected to a single WIFI router. Addresses are dynamically allocated by DHCP on the WIFI router. The socket is bind to exact local address instead of 0.0.0.0, and I am using port 19190. [ Thanks for reading my question :) ]

Following is the code for initializing the socket on all platforms. I do set the SO_BROADCAST flag on Mac/iOS otherwise UDP broadcast packet won't be sent successfully.

BOOL Socket::__Create(const struct sockaddr &BindTo, int addr_len, int nSocketType, BOOL reuse_addr, int AF)
    {
        ASSERT(m_hSocket == INVALID_SOCKET);
        m_hSocket = socket(AF, nSocketType, 0);

        if(INVALID_SOCKET != m_hSocket)
        {
            int on = 1;
            if(SOCK_STREAM == nSocketType)
            {   linger l = {1,0};
                VERIFY(0==::setsockopt(m_hSocket,SOL_SOCKET,SO_LINGER,(char*)&l,sizeof(linger)));
    #if defined(PLATFORM_MAC) || defined(PLATFORM_IOS)
                VERIFY(0==::setsockopt(m_hSocket,SOL_SOCKET,SO_NOSIGPIPE,(void *)&on, sizeof(on)));
    #endif
            }
    #if defined(PLATFORM_MAC) || defined(PLATFORM_IOS)
            else if(SOCK_DGRAM == nSocketType)
            {
                VERIFY(0==::setsockopt(m_hSocket,SOL_SOCKET,SO_BROADCAST,(void *)&on, sizeof(on)));
            }
    #endif
            if(reuse_addr)
            {   VERIFY(0==setsockopt(m_hSocket,SOL_SOCKET,SO_REUSEADDR,(char*)&on,sizeof(on)));
            }

            if(0==bind(m_hSocket,&BindTo,addr_len))
            {
                return TRUE;
            }
        }

        _LOG_WARNING("Socket Error = "<<GetLastError());
        Close();
        return FALSE;
    }

Here is the receiving code:

BOOL Socket::__RecvFrom(LPVOID pData, UINT len, UINT& len_out, struct sockaddr &target, int addr_len, BOOL Peek)
{
    SOCKET_SIZE_T la = addr_len;
    int l = (int)recvfrom(m_hSocket,(char*)pData,len,Peek?MSG_PEEK:0,&target,&la);
    if(l==SOCKET_ERROR)return FALSE;
    len_out = l;
    return la == addr_len;
}

Solution

  • Did you try to bind the socket to the broadcast address (the one you are sending to) ? – ElderBug

    Also, it's not working when you bind to 0.0.0.0 ? – ElderBug