UDP多网卡广播问题解决方案

楼主最近遇到了一个多网卡广播的问题,问题描述如下:
服务器上安装了多个网卡,当程序广播到255.255.255.255这个地址上时,
只有主网卡网段上的机子可以收到UDP数据,其他网段并不能收到数据.
针对这个问题,解决方案为:发送时绑定网卡的ip地址,比如两个网卡的ip地址为:192.168.23.2(主)
和10.20.30.4 广播时需要用两个socket分别绑定这两个ip,再进行发送.
如果两个网卡ip的第一位是一样的比如192.168.23.2(主)和192.169.24.2则可以通过设置
子网掩码255.0.0.0来将两个网络设置成一个内网从而进行广播,不需要本文中介绍的这么麻烦.
实现代码如下:

class UDPSender
{
public:
    UDPSender()
    {
        m_sock=-1;
    }
    ~UDPSender(){}
    bool SetRecvAddr(const char* addr,int port)
    {
        int sock=socket(AF_INET,SOCK_DGRAM,0);
        if(sock<0)
        {
            cout<<"socket init error!"<return false;
        }
        sockaddr_in addrSrv;
        addrSrv.sin_addr.s_addr=inet_addr(addr);
        addrSrv.sin_family=AF_INET;
        addrSrv.sin_port=htons(port);
        if((addrSrv.sin_addr.s_addr>>24)==0xff)//if addr end with 255 then broadcast
        {
            GetLocalIP();
            isBroadCast=true;
            string local=findlocalIp(addr);
            if(local.compare("")==0)
            {
                cout<<"find local ip error!"<return false;
            }
            sockaddr_in addrSrvLocal;
            addrSrvLocal.sin_addr.s_addr=inet_addr(local.c_str());
            addrSrvLocal.sin_family=AF_INET;
            addrSrvLocal.sin_port=0;//unuse
            if(bind(sock,(sockaddr *)&addrSrvLocal,sizeof(addrSrvLocal))!=0)
            {
                cout<<"bind local ip error!"<return false;
            }
            int opval=1;
            addrSrv.sin_addr.s_addr=htonl(INADDR_BROADCAST);
            setsockopt(sock,SOL_SOCKET,SO_BROADCAST,(char *)&opval,sizeof(opval));
        }
        m_sock=sock;
        m_sockaddr=addrSrv;
        return true;
    }
    void Send(char* buf,int bufsize)
    {
        sendto(m_sock,buf,bufsize,0,(struct sockaddr*)&m_sockaddr,sizeof(sockaddr));
    }
private:
    void GetLocalIP()
    {
        FILE *fstream=NULL;
        char buf[128];
        memset(buf,0,sizeof(buf));
        string cmd="/sbin/ifconfig |grep \"inet addr\"|awk \'{print $2}\'|awk -F \':\' \'{print $2}\'";// cmd: /sbin/ifconfig |greo "inet addr"|awk '{print $2}'|awk -F ':' '{print $2}'
        if(NULL==(fstream=popen(cmd.c_str(),"r")))
        {
            cout<<"ifconfig exec error"<return;
        }
        while(NULL != fgets(buf,sizeof(buf),fstream))
        {
            buf[strlen(buf)-1]='\0';//erase \n
            LocalIP.push_back(buf);
        }
        return;
    }
    string findlocalIp(string BCast)
    {
        if(LocalIP.size()==0)
        {
            cout<<"local ip empty"<return "";
        }
        int pos=BCast.find_first_of(".");
        if(pos<0)
        {
            cout<<"distination IP address format error!"<return "";
        }
        BCast[pos]=0;//compare first byte
        vector<string>::iter it=LocalIP.begin();
        for(;it!=LocalIP.end();it++)
        {
            string local=*it;
            pos=local.find_first_of(".");
            if(pos<0)
            {
                cout<<"local IP address format error"<return "";
            }
            local[pos]=0;
            if(strcmp(BCast.c_str(),local.c_str())==0)
            {
                return *it;
            }
        }
        return "";
    }
    vector<string> LocalIP;
    bool isBroadCast;
    int m_sock;
    sockaddr_in m_sockaddr;
}

下面是main函数

void main()
{
    UDPSender sender1,sender2;
    if(sender1.setRecvAddr("192.168.23.255",9999)==true)
    {
        cout<<"BroadCasting 192.168.23 ..."
        Sender.Send("hello",sizeof("hello"));
    }
    if(sender2.setRecvAddr("10.20.30.255",9998)==true)
    {
        cout<<"BroadCasting 10.20.30 ..."
        Sender2.Send("hello",sizeof("hello"));
    }
    return;
}

你可能感兴趣的:(linux,UDP/TCP,C++)