組播應(yīng)用層收不到-網(wǎng)卡綁定

問(wèn)題背景:

平臺(tái):Android
設(shè)備A:組播發(fā)送者,發(fā)送組播數(shù)據(jù)
設(shè)備B:組播接受者,接收組播數(shù)據(jù)
設(shè)備A與設(shè)備B通過(guò)有線(xiàn)連接,連接在設(shè)備B的eth0網(wǎng)卡上

問(wèn)題:
設(shè)備B在沒(méi)有通訊模塊網(wǎng)卡的情況下收得到設(shè)備A的組播數(shù)據(jù),一旦有了通訊模塊的撥號(hào)存在,則收不到A的組播數(shù)據(jù)了。但設(shè)備B上通過(guò)抓包,是能確認(rèn)有抓到組播數(shù)據(jù)進(jìn)來(lái),也就是說(shuō)eth0的網(wǎng)卡上,組播數(shù)據(jù)是進(jìn)來(lái)了

組播注冊(cè)偽代碼:

int listenSock = socket(AF_INET, SOCK_DGRAM, 0);
    if (-1 == listenSock)
    {
    printf("Create socket failed! listenSock=%d\n", listenSock);
    return -1;
    }

xint32_t opt = 1;
setsockopt(listenSock, SOL_SOCKET, SO_REUSEADDR, (const void *)&opt, sizeof(opt));

struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));

addr.sin_family = AF_INET;
addr.sin_port = htons(static_cast<uint16_t>(端口));
addr.sin_addr.s_addr = INADDR_ANY;
    if (bind(listenSock, reinterpret_cast<struct sockaddr*>(&addr), sizeof(addr)) == -1)
    {
     printf("Bind sock failed!!!\n");
     close(listenSock);
     return -1;
    }

struct ip_mreq group;
group.imr_multiaddr.s_addr = inet_addr("組播ip");
group.imr_interface.s_addr = INADDR_ANY;
    if (setsockopt(listenSock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&group, sizeof(group)) < 0)
    {
     close(listenSock);
     printf("Add membership fail! errno:%d\n", errno);
     return -2;
    }

    struct ifreq nif = {0};
    strcpy(nif.ifr_name, "eth0");
    if (setsockopt(listenSock, SOL_SOCKET, SO_BINDTODEVICE, (char *)&nif, sizeof(nif)) < 0)
    {
     close(listenSock);
     printf("Bind interface=eth0 fail!, errno:%d\n", errno);
     return -1;
    }

通過(guò)以上代碼,在存在通訊模塊的時(shí)候是收不到的。也懷疑過(guò)是否是因?yàn)楸惶砑恿薴ilter導(dǎo)致,后面也排除了,那么還有種可能,就是綁定網(wǎng)卡并沒(méi)有生效,我們雖然socket綁定到了eth0,但組播的加入也涉及網(wǎng)卡,我們這個(gè)方式因順序被加入到了其他網(wǎng)卡里,直接看修改,那么在添加組播組的時(shí)候也能綁定網(wǎng)卡,修改后的偽代碼如下:

int listenSock = socket(AF_INET, SOCK_DGRAM, 0);
    if (-1 == listenSock)
    {
    printf("Create socket failed!!! listenSock=%d\n", m_listenSock);
    return -1;
    }

 xint32_t opt = 1;
    setsockopt(listenSock, SOL_SOCKET, SO_REUSEADDR, (const void *)&opt, sizeof(opt));

struct sockaddr_in localAddr;
memset(&localAddr, 0, sizeof(localAddr));
localAddr.sin_family = AF_INET;
inet_pton(AF_INET, "組播ip", &localAddr.sin_addr);
localAddr.sin_port = htons((uint16_t)端口);
localAddr.sin_addr.s_addr = htonl(INADDR_ANY);
    if (::bind(listenSock, reinterpret_cast<struct sockaddr*>(&localAddr), sizeof(localAddr)) == -1)
    {
     printf("Bind sock failed!!!\n");
     close(listenSock);
     return -1;
    }

    struct ifreq nif;
    memset(&nif, 0, sizeof(ifreq));
    strcpy(nif.ifr_name, "eth0");
    if (::setsockopt(listenSock, SOL_SOCKET, SO_BINDTODEVICE, (char *)&nif, sizeof(ifreq)) < 0)
    {
     close(listenSock);
     printf("Bind interface=eth0 fail!, errno:%d\n", errno);
     return -1;
    }

 //關(guān)鍵修改在這
    struct ip_mreqn group;
 group.imr_multiaddr.s_addr = inet_addr("組播ip");
 group.imr_address.s_addr = htonl(INADDR_ANY);
 group.imr_ifindex = if_nametoindex("eth0");//在添加組的時(shí)候, 指定網(wǎng)卡
    if (::setsockopt(listenSock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&group, sizeof(group)) < 0)
    {
     close(listenSock);
     printf("Add membership interface=eth0 fail!, errno:%d\n", errno);
     return -2;
    }

也看到了,結(jié)構(gòu)體用得也不一樣了,其實(shí) ip_mreq 與 ip_mreqn時(shí)差不多的含義

//來(lái)源:#include <in.h>
/* Internet address. */
struct in_addr {
    __be32  s_addr;
};

/* Request struct for multicast socket ops */
struct ip_mreq  {
    struct in_addr imr_multiaddr;   /* IP multicast address of group */ //組播組組地址
    struct in_addr imr_interface;   /* local IP address of interface */ // 組播組的的網(wǎng)卡ip, 對(duì)應(yīng)的網(wǎng)卡能夠接收對(duì)應(yīng)多播組的數(shù)據(jù)包
};
  
struct ip_mreqn {
    struct in_addr  imr_multiaddr;      /* IP multicast address of group */
    struct in_addr  imr_address;        /* local IP address of interface */ //組播組的的網(wǎng)卡ip, 對(duì)應(yīng)的網(wǎng)卡能夠接收對(duì)應(yīng)多播組的數(shù)據(jù)包
    int     imr_ifindex;        /* Interface index */ //加入組播組的網(wǎng)卡index,優(yōu)先級(jí)高于以上地址
};

可以看到以下,ip_mreqn明確多了一個(gè)網(wǎng)卡指定。我在使用ip_mreq的時(shí)候也嘗試過(guò)將imr_interface指定為我eth0的ip來(lái)綁定,仍然無(wú)效。如果不是要收多個(gè)網(wǎng)卡的,可以使用以上方式修改,記錄借鑒

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容